root/boot/setup.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 !
   2 !       setup.s         (C) 1991 Linus Torvalds
   3 !
   4 ! setup.s is responsible for getting the system data from the BIOS,
   5 ! and putting them into the appropriate places in system memory.
   6 ! both setup.s and system has been loaded by the bootblock.
   7 !
   8 ! This code asks the bios for memory/disk/other parameters, and
   9 ! puts them in a "safe" place: 0x90000-0x901FF, ie where the
  10 ! boot-block used to be. It is then up to the protected mode
  11 ! system to read them from there before the area is overwritten
  12 ! for buffer-blocks.
  13 !
  14 
  15 ! NOTE! These had better be the same as in bootsect.s!
  16 #include <linux/config.h>
  17 
  18 INITSEG  = DEF_INITSEG  ! we move boot here - out of the way
  19 SYSSEG   = DEF_SYSSEG   ! system loaded at 0x10000 (65536).
  20 SETUPSEG = DEF_SETUPSEG ! this is the current segment
  21 
  22 .globl begtext, begdata, begbss, endtext, enddata, endbss
  23 .text
  24 begtext:
  25 .data
  26 begdata:
  27 .bss
  28 begbss:
  29 .text
  30 
  31 entry start
  32 start:
  33 
  34 ! ok, the read went well so we get current cursor position and save it for
  35 ! posterity.
  36 
  37         mov     ax,#INITSEG     ! this is done in bootsect already, but...
  38         mov     ds,ax
  39 
  40 ! Get memory size (extended mem, kB)
  41 
  42         mov     ah,#0x88
  43         int     0x15
  44         mov     [2],ax
  45 
  46 ! set the keyboard repeat rate to the max
  47 
  48         mov     ax,#0x0305
  49         mov     bx,#0x0000
  50         int     0x16
  51 
  52 ! check for EGA/VGA and some config parameters
  53 
  54         mov     ah,#0x12
  55         mov     bl,#0x10
  56         int     0x10
  57         mov     [8],ax
  58         mov     [10],bx
  59         mov     [12],cx
  60         mov     ax,#0x5019
  61         cmp     bl,#0x10
  62         je      novga
  63         call    chsvga
  64 novga:  mov     [14],ax
  65         mov     ah,#0x03        ! read cursor pos
  66         xor     bh,bh
  67         int     0x10            ! save it in known place, con_init fetches
  68         mov     [0],dx          ! it from 0x90000.
  69         
  70 ! Get video-card data:
  71         
  72         mov     ah,#0x0f
  73         int     0x10
  74         mov     [4],bx          ! bh = display page
  75         mov     [6],ax          ! al = video mode, ah = window width
  76 
  77 ! Get hd0 data
  78 
  79         mov     ax,#0x0000
  80         mov     ds,ax
  81         lds     si,[4*0x41]
  82         mov     ax,#INITSEG
  83         mov     es,ax
  84         mov     di,#0x0080
  85         mov     cx,#0x10
  86         cld
  87         rep
  88         movsb
  89 
  90 ! Get hd1 data
  91 
  92         mov     ax,#0x0000
  93         mov     ds,ax
  94         lds     si,[4*0x46]
  95         mov     ax,#INITSEG
  96         mov     es,ax
  97         mov     di,#0x0090
  98         mov     cx,#0x10
  99         cld
 100         rep
 101         movsb
 102 
 103 ! Check that there IS a hd1 :-)
 104 
 105         mov     ax,#0x01500
 106         mov     dl,#0x81
 107         int     0x13
 108         jc      no_disk1
 109         cmp     ah,#3
 110         je      is_disk1
 111 no_disk1:
 112         mov     ax,#INITSEG
 113         mov     es,ax
 114         mov     di,#0x0090
 115         mov     cx,#0x10
 116         mov     ax,#0x00
 117         cld
 118         rep
 119         stosb
 120 is_disk1:
 121 
 122 ! now we want to move to protected mode ...
 123 
 124         cli                     ! no interrupts allowed !
 125 
 126 ! first we move the system to it's rightful place
 127 
 128         mov     ax,#0x0000
 129         cld                     ! 'direction'=0, movs moves forward
 130 do_move:
 131         mov     es,ax           ! destination segment
 132         add     ax,#0x1000
 133         cmp     ax,#0x9000
 134         jz      end_move
 135         mov     ds,ax           ! source segment
 136         sub     di,di
 137         sub     si,si
 138         mov     cx,#0x8000
 139         rep
 140         movsw
 141         jmp     do_move
 142 
 143 ! then we load the segment descriptors
 144 
 145 end_move:
 146         mov     ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
 147         mov     ds,ax
 148         lidt    idt_48          ! load idt with 0,0
 149         lgdt    gdt_48          ! load gdt with whatever appropriate
 150 
 151 ! that was painless, now we enable A20
 152 
 153         call    empty_8042
 154         mov     al,#0xD1                ! command write
 155         out     #0x64,al
 156         call    empty_8042
 157         mov     al,#0xDF                ! A20 on
 158         out     #0x60,al
 159         call    empty_8042
 160 
 161 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
 162 ! we put them right after the intel-reserved hardware interrupts, at
 163 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
 164 ! messed this up with the original PC, and they haven't been able to
 165 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
 166 ! which is used for the internal hardware interrupts as well. We just
 167 ! have to reprogram the 8259's, and it isn't fun.
 168 
 169         mov     al,#0x11                ! initialization sequence
 170         out     #0x20,al                ! send it to 8259A-1
 171         .word   0x00eb,0x00eb           ! jmp $+2, jmp $+2
 172         out     #0xA0,al                ! and to 8259A-2
 173         .word   0x00eb,0x00eb
 174         mov     al,#0x20                ! start of hardware int's (0x20)
 175         out     #0x21,al
 176         .word   0x00eb,0x00eb
 177         mov     al,#0x28                ! start of hardware int's 2 (0x28)
 178         out     #0xA1,al
 179         .word   0x00eb,0x00eb
 180         mov     al,#0x04                ! 8259-1 is master
 181         out     #0x21,al
 182         .word   0x00eb,0x00eb
 183         mov     al,#0x02                ! 8259-2 is slave
 184         out     #0xA1,al
 185         .word   0x00eb,0x00eb
 186         mov     al,#0x01                ! 8086 mode for both
 187         out     #0x21,al
 188         .word   0x00eb,0x00eb
 189         out     #0xA1,al
 190         .word   0x00eb,0x00eb
 191         mov     al,#0xFF                ! mask off all interrupts for now
 192         out     #0x21,al
 193         .word   0x00eb,0x00eb
 194         out     #0xA1,al
 195 
 196 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
 197 ! need no steenking BIOS anyway (except for the initial loading :-).
 198 ! The BIOS-routine wants lots of unnecessary data, and it's less
 199 ! "interesting" anyway. This is how REAL programmers do it.
 200 !
 201 ! Well, now's the time to actually move into protected mode. To make
 202 ! things as simple as possible, we do no register set-up or anything,
 203 ! we let the gnu-compiled 32-bit programs do that. We just jump to
 204 ! absolute address 0x00000, in 32-bit protected mode.
 205 
 206         mov     ax,#0x0001      ! protected mode (PE) bit
 207         lmsw    ax              ! This is it!
 208         jmpi    0,8             ! jmp offset 0 of segment 8 (cs)
 209 
 210 ! This routine checks that the keyboard command queue is empty
 211 ! No timeout is used - if this hangs there is something wrong with
 212 ! the machine, and we probably couldn't proceed anyway.
 213 empty_8042:
 214         .word   0x00eb,0x00eb
 215         in      al,#0x64        ! 8042 status port
 216         test    al,#2           ! is input buffer full?
 217         jnz     empty_8042      ! yes - loop
 218         ret
 219 
 220 getkey:
 221         in      al,#0x60        ! Quick and dirty...
 222         .word   0x00eb,0x00eb           ! jmp $+2, jmp $+2
 223         mov     bl,al
 224         in      al,#0x61
 225         .word   0x00eb,0x00eb
 226         mov     ah,al
 227         or      al,#0x80
 228         out     #0x61,al
 229         .word   0x00eb,0x00eb
 230         mov     al,ah
 231         out     #0x61,al
 232         .word   0x00eb,0x00eb
 233         mov     al,bl
 234         ret
 235 
 236 ! Routine trying to recognize type of SVGA-board present (if any)
 237 ! and if it recognize one gives the choices of resolution it offers.
 238 ! If one is found the resolution chosen is given by al,ah (rows,cols).
 239 
 240 chsvga: cld
 241         push    ds
 242         push    cs
 243         pop     ds
 244         mov     ax,#0xc000
 245         mov     es,ax
 246         lea     si,msg1
 247         call    prtstr
 248 flush:  in      al,#0x60                ! Flush the keyboard buffer
 249         cmp     al,#0x82
 250         jb      nokey
 251         jmp     flush
 252 nokey:  call getkey
 253         cmp     al,#0x82
 254         jb      nokey
 255         cmp     al,#0xe0
 256         ja      nokey
 257         cmp     al,#0x9c
 258         je      svga
 259         mov     ax,#0x5019
 260         pop     ds
 261         ret
 262 svga:   cld
 263         lea     si,idati                ! Check ATI 'clues'
 264         mov     di,#0x31
 265         mov     cx,#0x09
 266         repe
 267         cmpsb
 268         jne     noati
 269         lea     si,dscati
 270         lea     di,moati
 271         lea     cx,selmod
 272         jmp     cx
 273 noati:  mov     ax,#0x200f              ! Check Ahead 'clues'
 274         mov     dx,#0x3ce
 275         out     dx,ax
 276         inc     dx
 277         in      al,dx
 278         cmp     al,#0x20
 279         je      isahed
 280         cmp     al,#0x21
 281         jne     noahed
 282 isahed: lea     si,dscahead
 283         lea     di,moahead
 284         lea     cx,selmod
 285         jmp     cx
 286 noahed: mov     dx,#0x3c3               ! Check Chips & Tech. 'clues'
 287         in      al,dx
 288         or      al,#0x10
 289         out     dx,al
 290         mov     dx,#0x104               
 291         in      al,dx
 292         mov     bl,al
 293         mov     dx,#0x3c3
 294         in      al,dx
 295         and     al,#0xef
 296         out     dx,al
 297         cmp     bl,[idcandt]
 298         jne     nocant
 299         lea     si,dsccandt
 300         lea     di,mocandt
 301         lea     cx,selmod
 302         jmp     cx
 303 nocant: mov     dx,#0x3d4               ! Check Cirrus 'clues'
 304         mov     al,#0x0c
 305         out     dx,al
 306         inc     dx
 307         in      al,dx
 308         mov     bl,al
 309         xor     al,al
 310         out     dx,al
 311         dec     dx
 312         mov     al,#0x1f
 313         out     dx,al
 314         inc     dx
 315         in      al,dx
 316         mov     bh,al
 317         xor     ah,ah
 318         shl     al,#4
 319         mov     cx,ax
 320         mov     al,bh
 321         shr     al,#4
 322         add     cx,ax
 323         shl     cx,#8
 324         add     cx,#6
 325         mov     ax,cx
 326         mov     dx,#0x3c4
 327         out     dx,ax
 328         inc     dx
 329         in      al,dx
 330         and     al,al
 331         jnz     nocirr
 332         mov     al,bh
 333         out     dx,al
 334         in      al,dx
 335         cmp     al,#0x01
 336         jne     nocirr
 337         call    rst3d4  
 338         lea     si,dsccirrus
 339         lea     di,mocirrus
 340         lea     cx,selmod
 341         jmp     cx
 342 rst3d4: mov     dx,#0x3d4
 343         mov     al,bl
 344         xor     ah,ah
 345         shl     ax,#8
 346         add     ax,#0x0c
 347         out     dx,ax
 348         ret     
 349 nocirr: call    rst3d4                  ! Check Everex 'clues'
 350         mov     ax,#0x7000
 351         xor     bx,bx
 352         int     0x10
 353         cmp     al,#0x70
 354         jne     noevrx
 355         shr     dx,#4
 356         cmp     dx,#0x678
 357         je      istrid
 358         cmp     dx,#0x236
 359         je      istrid
 360         lea     si,dsceverex
 361         lea     di,moeverex
 362         lea     cx,selmod
 363         jmp     cx
 364 istrid: lea     cx,ev2tri
 365         jmp     cx
 366 noevrx: lea     si,idgenoa              ! Check Genoa 'clues'
 367         xor     ax,ax
 368         seg es
 369         mov     al,[0x37]
 370         mov     di,ax
 371         mov     cx,#0x04
 372         dec     si
 373         dec     di
 374 l1:     inc     si
 375         inc     di
 376         mov     al,(si)
 377         seg es
 378         and     al,(di)
 379         cmp     al,(si)
 380         loope   l1
 381         cmp     cx,#0x00
 382         jne     nogen
 383         lea     si,dscgenoa
 384         lea     di,mogenoa
 385         lea     cx,selmod
 386         jmp     cx
 387 nogen:  cld
 388         lea     si,idparadise           ! Check Paradise 'clues'
 389         mov     di,#0x7d
 390         mov     cx,#0x04
 391         repe
 392         cmpsb
 393         jne     nopara
 394         lea     si,dscparadise
 395         lea     di,moparadise
 396         lea     cx,selmod
 397         jmp     cx
 398 nopara: mov     dx,#0x3c4               ! Check Trident 'clues'
 399         mov     al,#0x0e
 400         out     dx,al
 401         inc     dx
 402         in      al,dx
 403         xchg    ah,al
 404         mov     al,#0x00
 405         out     dx,al
 406         in      al,dx
 407         xchg    al,ah
 408         mov     bl,al           ! Strange thing ... in the book this wasn't
 409         and     bl,#0x02        ! necessary but it worked on my card which
 410         jz      setb2           ! is a trident. Without it the screen goes
 411         and     al,#0xfd        ! blurred ...
 412         jmp     clrb2           !
 413 setb2:  or      al,#0x02        !
 414 clrb2:  out     dx,al
 415         and     ah,#0x0f
 416         cmp     ah,#0x02
 417         jne     notrid
 418 ev2tri: lea     si,dsctrident
 419         lea     di,motrident
 420         lea     cx,selmod
 421         jmp     cx
 422 notrid: mov     dx,#0x3cd               ! Check Tseng 'clues'
 423         in      al,dx                   ! Could things be this simple ! :-)
 424         mov     bl,al
 425         mov     al,#0x55
 426         out     dx,al
 427         in      al,dx
 428         mov     ah,al
 429         mov     al,bl
 430         out     dx,al
 431         cmp     ah,#0x55
 432         jne     notsen
 433         lea     si,dsctseng
 434         lea     di,motseng
 435         lea     cx,selmod
 436         jmp     cx
 437 notsen: mov     dx,#0x3cc               ! Check Video7 'clues'
 438         in      al,dx
 439         mov     dx,#0x3b4
 440         and     al,#0x01
 441         jz      even7
 442         mov     dx,#0x3d4
 443 even7:  mov     al,#0x0c
 444         out     dx,al
 445         inc     dx
 446         in      al,dx
 447         mov     bl,al
 448         mov     al,#0x55
 449         out     dx,al
 450         in      al,dx
 451         dec     dx
 452         mov     al,#0x1f
 453         out     dx,al
 454         inc     dx
 455         in      al,dx
 456         mov     bh,al
 457         dec     dx
 458         mov     al,#0x0c
 459         out     dx,al
 460         inc     dx
 461         mov     al,bl
 462         out     dx,al
 463         mov     al,#0x55
 464         xor     al,#0xea
 465         cmp     al,bh
 466         jne     novid7
 467         lea     si,dscvideo7
 468         lea     di,movideo7
 469 selmod: push    si
 470         lea     si,msg2
 471         call    prtstr
 472         xor     cx,cx
 473         mov     cl,(di)
 474         pop     si
 475         push    si
 476         push    cx
 477 tbl:    pop     bx
 478         push    bx
 479         mov     al,bl
 480         sub     al,cl
 481         call    dprnt
 482         call    spcing
 483         lodsw
 484         xchg    al,ah
 485         call    dprnt
 486         xchg    ah,al
 487         push    ax
 488         mov     al,#0x78
 489         call    prnt1
 490         pop     ax
 491         call    dprnt
 492         call    docr
 493         loop    tbl
 494         pop     cx
 495         call    docr
 496         lea     si,msg3
 497         call    prtstr
 498         pop     si
 499         add     cl,#0x80
 500 nonum:  call    getkey
 501         cmp     al,#0x82
 502         jb      nonum
 503         cmp     al,#0x8b
 504         je      zero
 505         cmp     al,cl
 506         ja      nonum
 507         jmp     nozero
 508 zero:   sub     al,#0x0a
 509 nozero: sub     al,#0x80
 510         dec     al
 511         xor     ah,ah
 512         add     di,ax
 513         inc     di
 514         push    ax
 515         mov     al,(di)
 516         int     0x10
 517         pop     ax
 518         shl     ax,#1
 519         add     si,ax
 520         lodsw
 521         pop     ds
 522         ret
 523 novid7:
 524         mov     ax,#0x1112
 525         mov     bl,#0
 526         int     0x10            ! use 8x8 font set (50 lines on VGA)
 527 
 528         mov     ax,#0x1200
 529         mov     bl,#0x20
 530         int     0x10            ! use alternate print screen
 531 
 532         mov     ax,#0x1201
 533         mov     bl,#0x34
 534         int     0x10            ! turn off cursor emulation
 535 
 536         mov     ah,#0x01
 537         mov     cx,#0x0607
 538         int     0x10            ! turn on cursor (scan lines 6 to 7)
 539 
 540         pop     ds
 541         mov     ax,#0x5032      ! return 80x50
 542         ret
 543 
 544 ! Routine that 'tabs' to next col.
 545 
 546 spcing: mov     al,#0x2e
 547         call    prnt1
 548         mov     al,#0x20
 549         call    prnt1   
 550         mov     al,#0x20
 551         call    prnt1   
 552         mov     al,#0x20
 553         call    prnt1   
 554         mov     al,#0x20
 555         call    prnt1
 556         ret     
 557 
 558 ! Routine to print asciiz-string at DS:SI
 559 
 560 prtstr: lodsb
 561         and     al,al
 562         jz      fin
 563         call    prnt1
 564         jmp     prtstr
 565 fin:    ret
 566 
 567 ! Routine to print a decimal value on screen, the value to be
 568 ! printed is put in al (i.e 0-255). 
 569 
 570 dprnt:  push    ax
 571         push    cx
 572         mov     ah,#0x00                
 573         mov     cl,#0x0a
 574         idiv    cl
 575         cmp     al,#0x09
 576         jbe     lt100
 577         call    dprnt
 578         jmp     skip10
 579 lt100:  add     al,#0x30
 580         call    prnt1
 581 skip10: mov     al,ah
 582         add     al,#0x30
 583         call    prnt1   
 584         pop     cx
 585         pop     ax
 586         ret
 587 
 588 ! Part of above routine, this one just prints ascii al
 589 
 590 prnt1:  push    ax
 591         push    cx
 592         mov     bh,#0x00
 593         mov     cx,#0x01
 594         mov     ah,#0x0e
 595         int     0x10
 596         pop     cx
 597         pop     ax
 598         ret
 599 
 600 ! Prints <CR> + <LF>
 601 
 602 docr:   push    ax
 603         push    cx
 604         mov     bh,#0x00
 605         mov     ah,#0x0e
 606         mov     al,#0x0a
 607         mov     cx,#0x01
 608         int     0x10
 609         mov     al,#0x0d
 610         int     0x10
 611         pop     cx
 612         pop     ax
 613         ret     
 614         
 615 gdt:
 616         .word   0,0,0,0         ! dummy
 617 
 618         .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
 619         .word   0x0000          ! base address=0
 620         .word   0x9A00          ! code read/exec
 621         .word   0x00C0          ! granularity=4096, 386
 622 
 623         .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
 624         .word   0x0000          ! base address=0
 625         .word   0x9200          ! data read/write
 626         .word   0x00C0          ! granularity=4096, 386
 627 
 628 idt_48:
 629         .word   0                       ! idt limit=0
 630         .word   0,0                     ! idt base=0L
 631 
 632 gdt_48:
 633         .word   0x800           ! gdt limit=2048, 256 GDT entries
 634         .word   512+gdt,0x9     ! gdt base = 0X9xxxx
 635 
 636 msg1:           .ascii  "Press <RETURN> to see SVGA-modes available or any other key to continue."
 637                 db      0x0d, 0x0a, 0x0a, 0x00
 638 msg2:           .ascii  "Mode:  COLSxROWS:"
 639                 db      0x0d, 0x0a, 0x0a, 0x00
 640 msg3:           .ascii  "Choose mode by pressing the corresponding number."
 641                 db      0x0d, 0x0a, 0x00
 642                 
 643 idati:          .ascii  "761295520"
 644 idcandt:        .byte   0xa5
 645 idgenoa:        .byte   0x77, 0x00, 0x66, 0x99
 646 idparadise:     .ascii  "VGA="
 647 
 648 ! Manufacturer:   Numofmodes:   Mode:
 649 
 650 moati:          .byte   0x02,   0x23, 0x33 
 651 moahead:        .byte   0x05,   0x22, 0x23, 0x24, 0x2f, 0x34
 652 mocandt:        .byte   0x02,   0x60, 0x61
 653 mocirrus:       .byte   0x04,   0x1f, 0x20, 0x22, 0x31
 654 moeverex:       .byte   0x0a,   0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
 655 mogenoa:        .byte   0x0a,   0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
 656 moparadise:     .byte   0x02,   0x55, 0x54
 657 motrident:      .byte   0x07,   0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
 658 motseng:        .byte   0x05,   0x26, 0x2a, 0x23, 0x24, 0x22
 659 movideo7:       .byte   0x06,   0x40, 0x43, 0x44, 0x41, 0x42, 0x45
 660 
 661 !                       msb = Cols lsb = Rows:
 662 
 663 dscati:         .word   0x8419, 0x842c
 664 dscahead:       .word   0x842c, 0x8419, 0x841c, 0xa032, 0x5042
 665 dsccandt:       .word   0x8419, 0x8432
 666 dsccirrus:      .word   0x8419, 0x842c, 0x841e, 0x6425
 667 dsceverex:      .word   0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
 668 dscgenoa:       .word   0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
 669 dscparadise:    .word   0x8419, 0x842b
 670 dsctrident:     .word   0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
 671 dsctseng:       .word   0x503c, 0x6428, 0x8419, 0x841c, 0x842c
 672 dscvideo7:      .word   0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
 673         
 674 .text
 675 endtext:
 676 .data
 677 enddata:
 678 .bss
 679 endbss:

/* [previous][next][first][last][top][bottom][index][help] */