root/boot/setup.S

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

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