📄 setup.s
字号:
/* * 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 dont 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> * * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes * by Robert Schwebel, December 2001 <robert@schwebel.de> * * BIOS Enhanced Disk Drive support * by Matt Domsch <Matt_Domsch@dell.com> October 2002 * conformant to T13 Committee www.t13.org * projects 1572D, 1484D, 1386D, 1226DT */#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/edd.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 0x0203 # 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: .word bootsect_helper, SETUPSEGheap_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 __MAXMEM-1 # (Header version 0x0203 or later) # The highest safe address for # the contents of an initrdtrampoline: call start_of_setup .space 1024# 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)# Part of above routine, this one just prints ascii alprtchr: pushw %ax pushw %cx xorb %bh, %bh 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 pushw %cs popw %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: hlt 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:# 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.teleport.com/~acpi/acpihtml/topic245.htm#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 32 entries cmpb $E820MAX, %al jnl 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# to write everything into the same place.)meme801: stc # fix to work around buggy xorw %cx,%cx # BIOSes which dont clear/set xorw %dx,%dx # carry on pass/error of # e801h memory size call # or merely pass cx,dx though # without changing them. movw $0xe801, %ax int $0x15 jc mem88 cmpw $0x0, %cx # Kludge to handle BIOSes jne e801usecxdx # which report their extended cmpw $0x0, %dx # memory in AX/BX rather than jne e801usecxdx # CX/DX. The spec I have read movw %ax, %cx # seems to indicate AX/BX movw %bx, %dx # are more reasonable anyway...e801usecxdx: andl $0xffff, %edx # clear sign extend shll $6, %edx # and go from 64k to 1k chunks movl %edx, (0x1e0) # store extended memory size andl $0xffff, %ecx # clear sign extend addl %ecx, (0x1e0) # and add lower memory into # total size.# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or# 64mb, depending on the bios) in ax.mem88:#endif movb $0x88, %ah int $0x15 movw %ax, (2)# Set the keyboard repeat rate to the max movw $0x0305, %ax xorw %bx, %bx int $0x16# Check for video adapter and its parameters and allow the# user to browse video modes. call video # NOTE: we need %ds pointing # to bootsector# Get hd0 data... xorw %ax, %ax movw %ax, %ds ldsw (4 * 0x41), %si movw %cs, %ax # aka SETUPSEG subw $DELTA_INITSEG, %ax # aka INITSEG pushw %ax movw %ax, %es movw $0x0080, %di movw $0x10, %cx pushw %cx cld rep movsb# Get hd1 data... xorw %ax, %ax movw %ax, %ds ldsw (4 * 0x46), %si popw %cx popw %es movw $0x0090, %di rep movsb# Check that there IS a hd1 :-) movw $0x01500, %ax movb $0x81, %dl int $0x13 jc no_disk1 cmpb $3, %ah je is_disk1no_disk1: movw %cs, %ax # aka SETUPSEG subw $DELTA_INITSEG, %ax # aka INITSEG movw %ax, %es movw $0x0090, %di movw $0x10, %cx xorw %ax, %ax cld rep stosbis_disk1:# check for Micro Channel (MCA) bus movw %cs, %ax # aka SETUPSEG subw $DELTA_INITSEG, %ax # aka INITSEG movw %ax, %ds xorw %ax, %ax movw %ax, (0xa0) # set table length to 0 movb $0xc0, %ah stc int $0x15 # moves feature table to es:bx jc no_mca pushw %ds movw %es, %ax movw %ax, %ds movw %cs, %ax # aka SETUPSEG subw $DELTA_INITSEG, %ax # aka INITSEG movw %ax, %es movw %bx, %si movw $0xa0, %di movw (%si), %cx addw $2, %cx # table length is a short cmpw $0x10, %cx jc sysdesc_ok movw $0x10, %cx # we keep only first 16 bytessysdesc_ok: rep movsb popw %dsno_mca:# Check for PS/2 pointing device movw %cs, %ax # aka SETUPSEG subw $DELTA_INITSEG, %ax # aka INITSEG movw %ax, %ds movw $0, (0x1ff) # default is no pointing device int $0x11 # int 0x11: equipment list testb $0x04, %al # check if mouse installed jz no_psmouse movw $0xAA, (0x1ff) # device presentno_psmouse:#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)# Then check for an APM BIOS... # %ds points to the bootsector movw $0, 0x40 # version = 0 means no APM BIOS movw $0x05300, %ax # APM BIOS installation check xorw %bx, %bx int $0x15 jc done_apm_bios # Nope, no APM BIOS cmpw $0x0504d, %bx # Check for "PM" signature jne done_apm_bios # No signature, no APM BIOS andw $0x02, %cx # Is 32 bit supported? je done_apm_bios # No 32-bit, no (good) APM BIOS movw $0x05304, %ax # Disconnect first just in case xorw %bx, %bx int $0x15 # ignore return code movw $0x05303, %ax # 32 bit connect xorl %ebx, %ebx xorw %cx, %cx # paranoia :-) xorw %dx, %dx # ... xorl %esi, %esi # ... xorw %di, %di # ... int $0x15 jc no_32_apm_bios # Ack, error. movw %ax, (66) # BIOS code segment movl %ebx, (68) # BIOS entry point offset movw %cx, (72) # BIOS 16 bit code segment movw %dx, (74) # BIOS data segment movl %esi, (78) # BIOS code segment lengths movw %di, (82) # BIOS data segment length# Redo the installation check as the 32 bit connect# modifies the flags returned on some BIOSs movw $0x05300, %ax # APM BIOS installation check xorw %bx, %bx xorw %cx, %cx # paranoia int $0x15 jc apm_disconnect # error -> shouldn't happen cmpw $0x0504d, %bx # check for "PM" signature jne apm_disconnect # no sig -> shouldn't happen movw %ax, (64) # record the APM BIOS version movw %cx, (76) # and flags jmp done_apm_biosapm_disconnect: # Tidy up movw $0x05304, %ax # Disconnect xorw %bx, %bx int $0x15 # ignore return code jmp done_apm_biosno_32_apm_bios: andw $0xfffd, (76) # remove 32 bit support bitdone_apm_bios:#endif#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)# Do the BIOS Enhanced Disk Drive calls# This consists of two calls:# int 13h ah=41h "Check Extensions Present"# int 13h ah=48h "Get Device Parameters"## A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use# in the empty_zero_page at EDDBUF. The first four bytes of which are# used to store the device number, interface support map and version# results from fn41. The following 74 bytes are used to store# the results from fn48. Starting from device 80h, fn41, then fn48# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).# Then the pointer is incremented to store the data for the next call.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -