linux-0.12/boot/setup.S`

来源:互联网 发布:淘宝如何申请分销 编辑:程序博客网 时间:2024/05/22 17:14

setup.S 在进入system前执行,它首先调用bios获得各种硬件参数,然后进入保护模式。
。。代码看起来有点无聊

!!   setup.s     (C) 1991 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.!! NOTE! These had better be the same as in bootsect.s!#include <linux/config.h>;#define DEF_INITSEG    0x9000;#define DEF_SYSSEG 0x1000;#define DEF_SETUPSEG   0x9020;#define DEF_SYSSIZE    0x3000INITSEG  = DEF_INITSEG  ! we move boot here - out of the waySYSSEG   = DEF_SYSSEG   ! system loaded at 0x10000 (65536).SETUPSEG = DEF_SETUPSEG ! this is the current segment.globl begtext, begdata, begbss, endtext, enddata, endbss.textbegtext:.databegdata:.bssbegbss:.textentry startstart:! ok, the read went well so we get current cursor position and save it for! posterity.    mov ax,#INITSEG ! this is done in bootsect already, but...    mov ds,ax ;0x9000! Get memory size (extended mem, kB)    mov ah,#0x88    int 0x15    mov [2],ax;取系统所含扩展内存的大小,保存在0x90002! check for EGA/VGA and some config parameters    mov ah,#0x12    mov bl,#0x10    int 0x10    mov [8],ax    mov [10],bx  ;0x9000a 安装的显示内存 0x9000b 显示状态(彩色/单色)    mov [12],cx  ;0x9000c 显示卡特性参数    mov ax,#0x5019  ;检查屏幕是否是80*25的    cmp bl,#0x10    je  novga       ;如果中断 返回bl=0x10 表示不是vga显卡 跳 novga    call    chsvga  检测显示卡厂家和类型 修改显示的行列值novga:  mov [14],ax 保存当前的行列值    ;取屏幕当前光标位置    mov ah,#0x03    ! read cursor pos    xor bh,bh    int 0x10        ! save it in known place, con_init fetches    mov [0],dx      ! it from 0x90000.! Get video-card data:  取显卡当前的显示模式    mov ah,#0x0f    int 0x10    mov [4],bx      ! bh = display page    mov [6],ax      ! al = video mode, ah = window width! Get hd0 data 取第一个硬盘的信息    mov ax,#0x0000    mov ds,ax    lds si,[4*0x41]    mov ax,#INITSEG    mov es,ax    mov di,#0x0080    mov cx,#0x10    rep    movsb! Get hd1 data    mov ax,#0x0000    mov ds,ax    lds si,[4*0x46]    mov ax,#INITSEG    mov es,ax    mov di,#0x0090    mov cx,#0x10    rep    movsb! Check that there IS a hd1 :-) 检查是否有第二个硬盘    mov ax,#0x01500    mov dl,#0x81    int 0x13    jc  no_disk1    cmp ah,#3    je  is_disk1no_disk1:    mov ax,#INITSEG    mov es,ax    mov di,#0x0090    mov cx,#0x10    mov ax,#0x00    rep    stosbis_disk1:! now we want to move to protected mode ... 进入保护模式咯ing    cli         ! no interrupts allowed !! first we move the system to it's rightful place    mov ax,#0x0000    cld         ! 'direction'=0, movs moves forward    ;移动systemdo_move:    mov es,ax       ! destination segment    add ax,#0x1000    cmp ax,#0x9000    jz  end_move    mov ds,ax       ! source segment    sub di,di    sub si,si    mov     cx,#0x8000    rep    movsw    jmp do_move! then we load the segment descriptorsend_move:    mov ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)    mov ds,ax    lidt    idt_48      ! load idt with 0,0    lgdt    gdt_48      ! load gdt with whatever appropriate! that was painless, now we enable A20    call    empty_8042  ;等待8042状态恢复    mov al,#0xD1        ! command write    out #0x64,al    call    empty_8042    mov al,#0xDF        ! A20 on    out #0x60,al    call    empty_8042! well, that went ok, I hope. Now we have to reprogram the interrupts :-(! we put them right after the intel-reserved hardware interrupts, at! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really! messed this up with the original PC, and they haven't been able to! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,! which is used for the internal hardware interrupts as well. We just! have to reprogram the 8259's, and it isn't fun.;重新对8259进行编程    mov al,#0x11        ! initialization sequence    out #0x20,al        ! send it to 8259A-1    .word   0x00eb,0x00eb       ! jmp $+2, jmp $+2    out #0xA0,al        ! and to 8259A-2    .word   0x00eb,0x00eb    mov al,#0x20        ! start of hardware int's (0x20)    out #0x21,al    .word   0x00eb,0x00eb    mov al,#0x28        ! start of hardware int's 2 (0x28)    out #0xA1,al    .word   0x00eb,0x00eb    mov al,#0x04        ! 8259-1 is master    out #0x21,al    .word   0x00eb,0x00eb    mov al,#0x02        ! 8259-2 is slave    out #0xA1,al    .word   0x00eb,0x00eb    mov al,#0x01        ! 8086 mode for both    out #0x21,al    .word   0x00eb,0x00eb    out #0xA1,al    .word   0x00eb,0x00eb    mov al,#0xFF        ! mask off all interrupts for now    out #0x21,al    .word   0x00eb,0x00eb    out #0xA1,al;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8259 get done! well, that certainly wasn't fun :-(. Hopefully it works, and we don't! need no steenking BIOS anyway (except for the initial loading :-).! The BIOS-routine wants lots of unnecessary data, and it's less! "interesting" anyway. This is how REAL programmers do it.!! Well, now's the time to actually move into protected mode. To make! things as simple as possible, we do no register set-up or anything,! we let the gnu-compiled 32-bit programs do that. We just jump to! absolute address 0x00000, in 32-bit protected mode.    mov ax,#0x0001  ! protected mode (PE) bit    lmsw    ax      ! This is it!    设置cr0 进入到保护模式    jmpi    0,8     ! jmp offset 0 of segment 8 (cs)    ;8 =0b 0000 0000 0000 1-000    ;所以这里是使用 GDT中的第二个全局描述符    ;至此就会跳转执行system中的代码! This routine checks that the keyboard command queue is empty! No timeout is used - if this hangs there is something wrong with! the machine, and we probably couldn't proceed anyway.empty_8042:    .word   0x00eb,0x00eb    in  al,#0x64    ! 8042 status port    test    al,#2       ! is input buffer full?    jnz empty_8042  ! yes - loop    ret! Routine trying to recognize type of SVGA-board present (if any)! and if it recognize one gives the choices of resolution it offers.! If one is found the resolution chosen is given by al,ah (rows,cols).chsvga: cld    push    ds    push    cs    pop ds    mov     ax,#0xc000    mov es,ax    lea si,msg1    call    prtstrnokey:  in  al,#0x60    cmp al,#0x82    jb  nokey    cmp al,#0xe0    ja  nokey    cmp al,#0x9c    je  svga    mov ax,#0x5019    pop ds    retsvga:   lea     si,idati        ! Check ATI 'clues'    mov di,#0x31    mov     cx,#0x09    repe    cmpsb    jne noati    lea si,dscati    lea di,moati    lea cx,selmod    jmp cxnoati:  mov ax,#0x200f      ! Check Ahead 'clues'    mov dx,#0x3ce    out dx,ax    inc dx    in  al,dx    cmp al,#0x20    je  isahed    cmp al,#0x21    jne noahedisahed: lea si,dscahead    lea di,moahead    lea cx,selmod    jmp cxnoahed: mov dx,#0x3c3       ! Check Chips & Tech. 'clues'    in  al,dx    or  al,#0x10    out dx,al    mov dx,#0x104           in  al,dx    mov bl,al    mov dx,#0x3c3    in  al,dx    and al,#0xef    out dx,al    cmp bl,[idcandt]    jne nocant    lea si,dsccandt    lea di,mocandt    lea cx,selmod    jmp cxnocant: mov dx,#0x3d4       ! Check Cirrus 'clues'    mov al,#0x0c    out dx,al    inc dx    in  al,dx    mov bl,al    xor al,al    out dx,al    dec dx    mov al,#0x1f    out dx,al    inc dx    in  al,dx    mov bh,al    xor ah,ah    shl al,#4    mov cx,ax    mov al,bh    shr al,#4    add cx,ax    shl cx,#8    add cx,#6    mov ax,cx    mov dx,#0x3c4    out dx,ax    inc dx    in  al,dx    and al,al    jnz nocirr    mov al,bh    out dx,al    in  al,dx    cmp al,#0x01    jne nocirr    call    rst3d4      lea si,dsccirrus    lea di,mocirrus    lea cx,selmod    jmp cxrst3d4: mov dx,#0x3d4    mov al,bl    xor ah,ah    shl ax,#8    add ax,#0x0c    out dx,ax    ret nocirr: call    rst3d4          ! Check Everex 'clues'    mov ax,#0x7000    xor bx,bx    int 0x10    cmp al,#0x70    jne noevrx    shr dx,#4    cmp dx,#0x678    je  istrid    cmp dx,#0x236    je  istrid    lea si,dsceverex    lea di,moeverex    lea cx,selmod    jmp cxistrid: lea cx,ev2tri    jmp cxnoevrx: lea si,idgenoa      ! Check Genoa 'clues'    xor     ax,ax    seg es    mov al,[0x37]    mov di,ax    mov cx,#0x04    dec si    dec dil1: inc si    inc di    mov al,(si)    seg es    and al,(di)    cmp al,(si)    loope   l1    cmp cx,#0x00    jne nogen    lea si,dscgenoa    lea di,mogenoa    lea cx,selmod    jmp cxnogen:  lea si,idparadise       ! Check Paradise 'clues'    mov di,#0x7d    mov cx,#0x04    repe    cmpsb    jne nopara    lea si,dscparadise    lea di,moparadise    lea cx,selmod    jmp cxnopara: mov dx,#0x3c4       ! Check Trident 'clues'    mov al,#0x0e    out dx,al    inc dx    in  al,dx    xchg    ah,al    mov al,#0x00    out dx,al    in  al,dx    xchg    al,ah    mov bl,al       ! Strange thing ... in the book this wasn't    and bl,#0x02    ! necessary but it worked on my card which    jz  setb2       ! is a trident. Without it the screen goes    and al,#0xfd    ! blurred ...    jmp clrb2       !setb2:  or  al,#0x02    !clrb2:  out dx,al    and ah,#0x0f    cmp ah,#0x02    jne notridev2tri: lea si,dsctrident    lea di,motrident    lea cx,selmod    jmp cxnotrid: mov dx,#0x3cd       ! Check Tseng 'clues'    in  al,dx           ! Could things be this simple ! :-)    mov bl,al    mov al,#0x55    out dx,al    in  al,dx    mov ah,al    mov al,bl    out dx,al    cmp ah,#0x55    jne notsen    lea si,dsctseng    lea di,motseng    lea cx,selmod    jmp cxnotsen: mov dx,#0x3cc       ! Check Video7 'clues'    in  al,dx    mov dx,#0x3b4    and al,#0x01    jz  even7    mov dx,#0x3d4even7:  mov al,#0x0c    out dx,al    inc dx    in  al,dx    mov bl,al    mov al,#0x55    out dx,al    in  al,dx    dec dx    mov al,#0x1f    out dx,al    inc dx    in  al,dx    mov bh,al    dec dx    mov al,#0x0c    out dx,al    inc dx    mov al,bl    out dx,al    mov al,#0x55    xor al,#0xea    cmp al,bh    jne novid7    lea si,dscvideo7    lea di,movideo7selmod: push    si    lea si,msg2    call    prtstr    xor cx,cx    mov cl,(di)    pop si    push    si    push    cxtbl:    pop bx    push    bx    mov al,bl    sub al,cl    call    dprnt    call    spcing    lodsw    xchg    al,ah    call    dprnt    xchg    ah,al    push    ax    mov al,#0x78    call    prnt1    pop ax    call    dprnt    call    docr    loop    tbl    pop cx    call    docr    lea si,msg3    call    prtstr    pop si    add cl,#0x80nonum:  in  al,#0x60    ! Quick and dirty...    cmp al,#0x82    jb  nonum    cmp al,#0x8b    je  zero    cmp al,cl    ja  nonum    jmp nozerozero:   sub al,#0x0anozero: sub al,#0x80    dec al    xor ah,ah    add di,ax    inc di    push    ax    mov al,(di)    int     0x10    pop ax    shl ax,#1    add si,ax    lodsw    pop ds    retnovid7: pop ds  ! Here could be code to support standard 80x50,80x30    mov ax,#0x5019      ret! Routine that 'tabs' to next col.spcing: mov al,#0x2e    call    prnt1    mov al,#0x20    call    prnt1       mov al,#0x20    call    prnt1       mov al,#0x20    call    prnt1       mov al,#0x20    call    prnt1    ret ! Routine to print asciiz-string at DS:SIprtstr: lodsb    and al,al    jz  fin    call    prnt1    jmp prtstrfin:    ret! Routine to print a decimal value on screen, the value to be! printed is put in al (i.e 0-255). dprnt:  push    ax    push    cx    mov ah,#0x00            mov cl,#0x0a    idiv    cl    cmp al,#0x09    jbe lt100    call    dprnt    jmp skip10lt100:  add al,#0x30    call    prnt1skip10: mov al,ah    add al,#0x30    call    prnt1       pop cx    pop ax    ret! Part of above routine, this one just prints ascii alprnt1:  push    ax    push    cx    mov bh,#0x00    mov cx,#0x01    mov ah,#0x0e    int 0x10    pop cx    pop ax    ret! Prints <CR> + <LF>docr:   push    ax    push    cx    mov bh,#0x00    mov ah,#0x0e    mov al,#0x0a    mov cx,#0x01    int 0x10    mov al,#0x0d    int 0x10    pop cx    pop ax    ret gdt:    .word   0,0,0,0     ! dummy    .word   0x07FF      ! 8Mb - limit=2047 (2048*4096=8Mb)    .word   0x0000      ! base address=0    .word   0x9A00      ! code read/exec    .word   0x00C0      ! granularity=4096, 386    .word   0x07FF      ! 8Mb - limit=2047 (2048*4096=8Mb)    .word   0x0000      ! base address=0    .word   0x9200      ! data read/write    .word   0x00C0      ! granularity=4096, 386idt_48:    .word   0           ! idt limit=0    .word   0,0         ! idt base=0Lgdt_48:    .word   0x800       ! gdt limit=2048, 256 GDT entries    .word   512+gdt,0x9 ! gdt base = 0X9xxxxmsg1:       .ascii  "Press <RETURN> to see SVGA-modes available or any other key to continue."        db  0x0d, 0x0a, 0x0a, 0x00msg2:       .ascii  "Mode:  COLSxROWS:"        db  0x0d, 0x0a, 0x0a, 0x00msg3:       .ascii  "Choose mode by pressing the corresponding number."        db  0x0d, 0x0a, 0x00idati:      .ascii  "761295520"idcandt:    .byte   0xa5idgenoa:    .byte   0x77, 0x00, 0x66, 0x99idparadise: .ascii  "VGA="! Manufacturer:   Numofmodes:   Mode:moati:      .byte   0x02,   0x23, 0x33 moahead:    .byte   0x05,   0x22, 0x23, 0x24, 0x2f, 0x34mocandt:    .byte   0x02,   0x60, 0x61mocirrus:   .byte   0x04,   0x1f, 0x20, 0x22, 0x31moeverex:   .byte   0x0a,   0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40mogenoa:    .byte   0x0a,   0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78moparadise: .byte   0x02,   0x55, 0x54motrident:  .byte   0x07,   0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5amotseng:    .byte   0x05,   0x26, 0x2a, 0x23, 0x24, 0x22movideo7:   .byte   0x06,   0x40, 0x43, 0x44, 0x41, 0x42, 0x45!           msb = Cols lsb = Rows:dscati:     .word   0x8419, 0x842cdscahead:   .word   0x842c, 0x8419, 0x841c, 0xa032, 0x5042dsccandt:   .word   0x8419, 0x8432dsccirrus:  .word   0x8419, 0x842c, 0x841e, 0x6425dsceverex:  .word   0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841edscgenoa:   .word   0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644bdscparadise:    .word   0x8419, 0x842bdsctrident: .word   0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843cdsctseng:   .word   0x503c, 0x6428, 0x8419, 0x841c, 0x842cdscvideo7:  .word   0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c.textendtext:.dataenddata:.bssendbss:

当setup执行后,system模块被移动到0x0000开始处,而从0x90000开始存放了内核会使用的系统基本参数。

此时临时全局描述表中有三个描述符:第一个是NULL不使用,另外两个是代码段描述符和数据段描述符,他们都指向系统模块的起始处,0x0000,最后一句jmpi 0,8 会跳转到system模块的开始部分,也就是head.s 继续执行下去;

0 0
原创粉丝点击