root/arch/i386/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 ! Move PS/2 aux init code to psaux.c
  15 ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
  16 !
  17 ! some changes and additional features by Christoph Niemann,
  18 ! March 1993/June 1994 (Christoph.Niemann@linux.org)
  19 !
  20 ! add APM BIOS checking by Stephen Rothwell, May 1994
  21 ! (Stephen.Rothwell@pd.necisa.oz.au)
  22 !
  23 ! High load stuff, initrd support and position independency
  24 ! by Hans Lermen & Werner Almesberger, February 1996
  25 ! <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
  26 !
  27 ! Video handling moved to video.S by Martin Mares, March 1996
  28 ! <mj@k332.feld.cvut.cz>
  29 
  30 ! NOTE! These had better be the same as in bootsect.s!
  31 #define __ASSEMBLY__
  32 #include <linux/config.h>
  33 #include <asm/segment.h>
  34 #include <linux/version.h>
  35 #include <linux/compile.h>
  36 
  37 ! Signature words to ensure LILO loaded us right
  38 #define SIG1    0xAA55
  39 #define SIG2    0x5A5A
  40 
  41 INITSEG  = DEF_INITSEG  ! 0x9000, we move boot here - out of the way
  42 SYSSEG   = DEF_SYSSEG   ! 0x1000, system loaded at 0x10000 (65536).
  43 SETUPSEG = DEF_SETUPSEG ! 0x9020, this is the current segment
  44                         ! ... and the former contents of CS
  45 DELTA_INITSEG = SETUPSEG - INITSEG ! 0x0020
  46 
  47 .globl begtext, begdata, begbss, endtext, enddata, endbss
  48 .text
  49 begtext:
  50 .data
  51 begdata:
  52 .bss
  53 begbss:
  54 .text
  55 
  56 entry start
  57 start:
  58         jmp     start_of_setup
  59 ! ------------------------ start of header --------------------------------
  60 !
  61 ! SETUP-header, must start at CS:2 (old 0x9020:2)
  62 !
  63                 .ascii  "HdrS"          ! Signature for SETUP-header
  64                 .word   0x0201          ! Version number of header format
  65                                         ! (must be >= 0x0105
  66                                         ! else old loadlin-1.5 will fail)
  67 realmode_swtch: .word   0,0             ! default_switch,SETUPSEG
  68 start_sys_seg:  .word   SYSSEG
  69                 .word   kernel_version  ! pointing to kernel version string
  70   ! note: above part of header is compatible with loadlin-1.5 (header v1.5),
  71   !        must not change it
  72 
  73 type_of_loader: .byte   0               ! = 0, old one (LILO, Loadlin,
  74                                         !      Bootlin, SYSLX, bootsect...)
  75                                         ! else it is set by the loader:
  76                                         ! 0xTV: T=0 for LILO
  77                                         !       T=1 for Loadlin
  78                                         !       T=2 for bootsect-loader
  79                                         !       T=3 for SYSLX
  80                                         !       T=4 for ETHERBOOT
  81                                         !       V = version
  82 loadflags:      .byte   0       ! unused bits =0 (reserved for future development)
  83 LOADED_HIGH     = 1             ! bit within loadflags,
  84                                 ! if set, then the kernel is loaded high
  85 CAN_USE_HEAP    = 0x80          ! if set, the loader also has set heap_end_ptr
  86                                 ! to tell how much space behind setup.S
  87                                 | can be used for heap purposes.
  88                                 ! Only the loader knows what is free!
  89 setup_move_size: .word  0x8000  ! size to move, when we (setup) are not
  90                                 ! loaded at 0x90000. We will move ourselves
  91                                 ! to 0x90000 then just before jumping into
  92                                 ! the kernel. However, only the loader
  93                                 ! know how much of data behind us also needs
  94                                 ! to be loaded.
  95 code32_start:   .long   0x1000          ! here loaders can put a different
  96                                         ! start address for 32-bit code.
  97                                         !   0x1000 = default for zImage
  98                                         ! 0x100000 = default for big kernel
  99 ramdisk_image:  .long   0       ! address of loaded ramdisk image
 100                                 ! Here the loader (or kernel generator) puts
 101                                 ! the 32-bit address were it loaded the image.
 102                                 ! This only will be interpreted by the kernel.
 103 ramdisk_size:   .long   0       ! its size in bytes
 104 bootsect_kludge:
 105                 .word   bootsect_helper,SETUPSEG
 106 heap_end_ptr:   .word   modelist+1024   ! space from here (exclusive) down to
 107                                 ! end of setup code can be used by setup
 108                                 ! for local heap purposes.
 109 ! ------------------------ end of header ----------------------------------
 110 
 111 start_of_setup:
 112 ! Bootlin depends on this being done early
 113         mov     ax,#0x01500
 114         mov     dl,#0x81
 115         int     0x13
 116 
 117 ! set DS=CS, we know that SETUPSEG == CS at this point
 118         mov     ax,cs           ! aka #SETUPSEG
 119         mov     ds,ax
 120 
 121 ! Check signature at end of setup
 122         cmp     setup_sig1,#SIG1
 123         jne     bad_sig
 124         cmp     setup_sig2,#SIG2
 125         jne     bad_sig
 126         jmp     good_sig1
 127 
 128 ! Routine to print asciiz-string at DS:SI
 129 
 130 prtstr: lodsb
 131         and     al,al
 132         jz      fin
 133         call    prtchr
 134         jmp     prtstr
 135 fin:    ret
 136 
 137 ! Space printing
 138 
 139 prtsp2: call    prtspc          ! Print double space
 140 prtspc: mov     al,#0x20        ! Print single space (fall-thru!)
 141 
 142 ! Part of above routine, this one just prints ascii al
 143 
 144 prtchr: push    ax
 145         push    cx
 146         xor     bh,bh
 147         mov     cx,#0x01
 148         mov     ah,#0x0e
 149         int     0x10
 150         pop     cx
 151         pop     ax
 152         ret
 153 
 154 beep:   mov     al,#0x07
 155         jmp     prtchr
 156         
 157 no_sig_mess:    .ascii  "No setup signature found ..."
 158                 db      0x00
 159 
 160 good_sig1:
 161         jmp     good_sig
 162 
 163 ! We now have to find the rest of the setup code/data
 164 bad_sig:
 165         mov     ax,cs           ! aka #SETUPSEG
 166         sub     ax,#DELTA_INITSEG ! aka #INITSEG
 167         mov     ds,ax
 168         xor     bh,bh
 169         mov     bl,[497]        ! get setup sects from boot sector
 170         sub     bx,#4           ! LILO loads 4 sectors of setup
 171         shl     bx,#8           ! convert to words
 172         mov     cx,bx
 173         shr     bx,#3           ! convert to segment
 174         add     bx,#SYSSEG
 175         seg cs
 176         mov     start_sys_seg,bx
 177 
 178 ! Move rest of setup code/data to here
 179         mov     di,#2048        ! four sectors loaded by LILO
 180         sub     si,si
 181         mov     ax,cs           ! aka #SETUPSEG
 182         mov     es,ax
 183         mov     ax,#SYSSEG
 184         mov     ds,ax
 185         rep
 186         movsw
 187 
 188         mov     ax,cs           ! aka #SETUPSEG
 189         mov     ds,ax
 190         cmp     setup_sig1,#SIG1
 191         jne     no_sig
 192         cmp     setup_sig2,#SIG2
 193         jne     no_sig
 194         jmp     good_sig
 195 
 196 no_sig:
 197         lea     si,no_sig_mess
 198         call    prtstr
 199 no_sig_loop:
 200         jmp     no_sig_loop
 201 
 202 good_sig:
 203         mov     ax,cs           ! aka #SETUPSEG
 204         sub     ax,#DELTA_INITSEG ! aka #INITSEG
 205         mov     ds,ax
 206 
 207 ! check if an old loader tries to load a big-kernel
 208         seg cs
 209         test    byte ptr loadflags,#LOADED_HIGH ! have we a big kernel ?
 210         jz      loader_ok       ! NO, no danger even for old loaders
 211                                 ! YES, we have a big-kernel
 212         seg cs
 213         cmp     byte ptr type_of_loader,#0 ! have we one of the new loaders ?
 214         jnz     loader_ok       ! YES, ok
 215                                 ! NO, we have an old loader, must give up
 216         push    cs
 217         pop     ds
 218         lea     si,loader_panic_mess
 219         call    prtstr
 220         jmp     no_sig_loop
 221 loader_panic_mess: 
 222         .ascii  "Wrong loader, giving up..."
 223         db      0
 224 
 225 loader_ok:
 226 ! Get memory size (extended mem, kB)
 227 
 228         mov     ah,#0x88
 229         int     0x15
 230         mov     [2],ax
 231 
 232 ! Set the keyboard repeat rate to the max
 233 
 234         mov     ax,#0x0305
 235         xor     bx,bx           ! clear bx
 236         int     0x16
 237 
 238 ! Check for video adapter and its parameters and allow the
 239 ! user to browse video modes.
 240 
 241         call    video   ! NOTE: we need DS pointing to bootsector
 242 
 243 ! Get hd0 data
 244 
 245         xor     ax,ax           ! clear ax
 246         mov     ds,ax
 247         lds     si,[4*0x41]
 248         mov     ax,cs           ! aka #SETUPSEG
 249         sub     ax,#DELTA_INITSEG ! aka #INITSEG
 250         push    ax
 251         mov     es,ax
 252         mov     di,#0x0080
 253         mov     cx,#0x10
 254         push    cx
 255         cld
 256         rep
 257         movsb
 258 
 259 ! Get hd1 data
 260 
 261         xor     ax,ax           ! clear ax
 262         mov     ds,ax
 263         lds     si,[4*0x46]
 264         pop     cx
 265         pop     es
 266         mov     di,#0x0090
 267         rep
 268         movsb
 269 
 270 ! Check that there IS a hd1 :-)
 271 
 272         mov     ax,#0x01500
 273         mov     dl,#0x81
 274         int     0x13
 275         jc      no_disk1
 276         cmp     ah,#3
 277         je      is_disk1
 278 no_disk1:
 279         mov     ax,cs           ! aka #SETUPSEG
 280         sub     ax,#DELTA_INITSEG ! aka #INITSEG
 281         mov     es,ax
 282         mov     di,#0x0090
 283         mov     cx,#0x10
 284         xor     ax,ax           ! clear ax
 285         cld
 286         rep
 287         stosb
 288 is_disk1:
 289 
 290 ! Check for PS/2 pointing device
 291 
 292         mov     ax,cs           ! aka #SETUPSEG
 293         sub     ax,#DELTA_INITSEG ! aka #INITSEG
 294         mov     ds,ax
 295         mov     [0x1ff],#0      ! default is no pointing device
 296         int     0x11            ! int 0x11: equipment determination
 297         test    al,#0x04        ! check if pointing device installed
 298         jz      no_psmouse
 299         mov     [0x1ff],#0xaa   ! device present
 300 no_psmouse:
 301 
 302 #ifdef CONFIG_APM
 303 ! check for APM BIOS
 304                 ! NOTE: DS is pointing to the bootsector
 305                 !
 306         mov     [64],#0         ! version == 0 means no APM BIOS
 307 
 308         mov     ax,#0x05300     ! APM BIOS installation check
 309         xor     bx,bx
 310         int     0x15
 311         jc      done_apm_bios   ! error -> no APM BIOS
 312 
 313         cmp     bx,#0x0504d     ! check for "PM" signature
 314         jne     done_apm_bios   ! no signature -> no APM BIOS
 315 
 316         mov     [64],ax         ! record the APM BIOS version
 317         mov     [76],cx         !       and flags
 318         and     cx,#0x02        ! Is 32 bit supported?
 319         je      done_apm_bios   !       no ...
 320 
 321         mov     ax,#0x05304     ! Disconnect first just in case
 322         xor     bx,bx
 323         int     0x15            ! ignore return code
 324 
 325         mov     ax,#0x05303     ! 32 bit connect
 326         xor     bx,bx
 327         int     0x15
 328         jc      no_32_apm_bios  ! error
 329 
 330         mov     [66],ax         ! BIOS code segment
 331         mov     [68],ebx        ! BIOS entry point offset
 332         mov     [72],cx         ! BIOS 16 bit code segment
 333         mov     [74],dx         ! BIOS data segment
 334         mov     [78],si         ! BIOS code segment length
 335         mov     [80],di         ! BIOS data segment length
 336         jmp     done_apm_bios
 337 
 338 no_32_apm_bios:
 339         and     [76], #0xfffd   ! remove 32 bit support bit
 340 
 341 done_apm_bios:
 342 #endif
 343 
 344 ! Now we want to move to protected mode ...
 345 
 346         seg cs
 347         cmp     realmode_swtch,#0
 348         jz      rmodeswtch_normal
 349         seg cs
 350         callf   far * realmode_swtch
 351         jmp     rmodeswtch_end
 352 rmodeswtch_normal:
 353         push    cs
 354         call    default_switch
 355 rmodeswtch_end:
 356 
 357 ! we get the code32 start address and modify the below 'jmpi'
 358 ! (loader may have changed it)
 359         seg cs
 360         mov     eax,code32_start
 361         seg cs
 362         mov     code32,eax
 363 
 364 ! Now we move the system to its rightful place
 365 ! ...but we check, if we have a big-kernel.
 366 ! in this case we *must* not move it ...
 367         seg cs
 368         test    byte ptr loadflags,#LOADED_HIGH
 369         jz      do_move0        ! we have a normal low loaded zImage
 370                                 ! we have a high loaded big kernel
 371         jmp     end_move        ! ... and we skip moving
 372 
 373 do_move0:
 374         mov     ax,#0x100       ! start of destination segment
 375         mov     bp,cs           ! aka #SETUPSEG
 376         sub     bp,#DELTA_INITSEG ! aka #INITSEG
 377         seg cs
 378         mov     bx,start_sys_seg        ! start of source segment
 379         cld                     ! 'direction'=0, movs moves forward
 380 do_move:
 381         mov     es,ax           ! destination segment
 382         inc     ah              ! instead of add ax,#0x100
 383         mov     ds,bx           ! source segment
 384         add     bx,#0x100
 385         sub     di,di
 386         sub     si,si
 387         mov     cx,#0x800
 388         rep
 389         movsw
 390         cmp     bx,bp           ! we assume start_sys_seg > 0x200,
 391                                 ! so we will perhaps read one page more then
 392                                 ! needed, but never overwrite INITSEG because
 393                                 ! destination is minimum one page below source
 394         jb      do_move
 395 
 396 ! then we load the segment descriptors
 397 
 398 end_move:
 399         mov     ax,cs ! aka #SETUPSEG   ! right, forgot this at first. didn't work :-)
 400         mov     ds,ax
 401 
 402 ! If we have our code not at 0x90000, we need to move it there now.
 403 ! We also then need to move the params behind it (commandline)
 404 ! Because we would overwrite the code on the current IP, we move
 405 ! it in two steps, jumping high after the first one.
 406         mov     ax,cs
 407         cmp     ax,#SETUPSEG
 408         je      end_move_self
 409         cli     ! make sure we really have interrupts disabled !
 410                 ! because after this the stack should not be used
 411         sub     ax,#DELTA_INITSEG ! aka #INITSEG
 412         mov     dx,ss
 413         cmp     dx,ax
 414         jb      move_self_1
 415         add     dx,#INITSEG
 416         sub     dx,ax           ! this will be SS after the move
 417 move_self_1:
 418         mov     ds,ax
 419         mov     ax,#INITSEG     ! real INITSEG
 420         mov     es,ax
 421         seg cs
 422         mov     cx,setup_move_size
 423         std             ! we have to move up, so we use direction down
 424                         ! because the areas may overlap
 425         mov     di,cx
 426         dec     di
 427         mov     si,di
 428         sub     cx,#move_self_here+0x200
 429         rep
 430         movsb
 431         jmpi    move_self_here,SETUPSEG ! jump to our final place
 432 move_self_here:
 433         mov     cx,#move_self_here+0x200
 434         rep
 435         movsb
 436         mov     ax,#SETUPSEG
 437         mov     ds,ax
 438         mov     ss,dx
 439                         ! now we are at the right place
 440 end_move_self:
 441 
 442         lidt    idt_48          ! load idt with 0,0
 443         lgdt    gdt_48          ! load gdt with whatever appropriate
 444 
 445 ! that was painless, now we enable A20
 446 
 447         call    empty_8042
 448         mov     al,#0xD1                ! command write
 449         out     #0x64,al
 450         call    empty_8042
 451         mov     al,#0xDF                ! A20 on
 452         out     #0x60,al
 453         call    empty_8042
 454 
 455 ! make sure any possible coprocessor is properly reset..
 456 
 457         xor     ax,ax
 458         out     #0xf0,al
 459         call    delay
 460         out     #0xf1,al
 461         call    delay
 462 
 463 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
 464 ! we put them right after the intel-reserved hardware interrupts, at
 465 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
 466 ! messed this up with the original PC, and they haven't been able to
 467 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
 468 ! which is used for the internal hardware interrupts as well. We just
 469 ! have to reprogram the 8259's, and it isn't fun.
 470 
 471         mov     al,#0x11                ! initialization sequence
 472         out     #0x20,al                ! send it to 8259A-1
 473         call    delay
 474         out     #0xA0,al                ! and to 8259A-2
 475         call    delay
 476         mov     al,#0x20                ! start of hardware int's (0x20)
 477         out     #0x21,al
 478         call    delay
 479         mov     al,#0x28                ! start of hardware int's 2 (0x28)
 480         out     #0xA1,al
 481         call    delay
 482         mov     al,#0x04                ! 8259-1 is master
 483         out     #0x21,al
 484         call    delay
 485         mov     al,#0x02                ! 8259-2 is slave
 486         out     #0xA1,al
 487         call    delay
 488         mov     al,#0x01                ! 8086 mode for both
 489         out     #0x21,al
 490         call    delay
 491         out     #0xA1,al
 492         call    delay
 493         mov     al,#0xFF                ! mask off all interrupts for now
 494         out     #0xA1,al
 495         call    delay
 496         mov     al,#0xFB                ! mask all irq's but irq2 which
 497         out     #0x21,al                ! is cascaded
 498 
 499 ! Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
 500 ! need no steenking BIOS anyway (except for the initial loading :-).
 501 ! The BIOS-routine wants lots of unnecessary data, and it's less
 502 ! "interesting" anyway. This is how REAL programmers do it.
 503 !
 504 ! Well, now's the time to actually move into protected mode. To make
 505 ! things as simple as possible, we do no register set-up or anything,
 506 ! we let the gnu-compiled 32-bit programs do that. We just jump to
 507 ! absolute address 0x1000 (or the loader supplied one),
 508 ! in 32-bit protected mode.
 509 !
 510 ! Note that the short jump isn't strictly needed, although there are
 511 ! reasons why it might be a good idea. It won't hurt in any case.
 512 !
 513         mov     ax,#1           ! protected mode (PE) bit
 514         lmsw    ax              ! This is it!
 515         jmp     flush_instr
 516 flush_instr:
 517         xor     bx,bx           ! Flag to indicate a boot
 518 
 519 ! NOTE: For high loaded big kernels we need a
 520 !       jmpi    0x100000,KERNEL_CS
 521 !
 522 !       but we yet haven't reloaded the CS register, so the default size 
 523 !       of the target offset still is 16 bit.
 524 !       However, using an operant prefix (0x66), the CPU will properly
 525 !       take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
 526 !       Manual, Mixing 16-bit and 32-bit code, page 16-6)
 527         db      0x66,0xea       ! prefix + jmpi-opcode
 528 code32: dd      0x1000          ! will be set to 0x100000 for big kernels
 529         dw      KERNEL_CS
 530 
 531 
 532 kernel_version: .ascii  UTS_RELEASE
 533                 .ascii  " ("
 534                 .ascii  LINUX_COMPILE_BY
 535                 .ascii  "@"
 536                 .ascii  LINUX_COMPILE_HOST
 537                 .ascii  ") "
 538                 .ascii  UTS_VERSION
 539                 db      0
 540 
 541 ! This is the default real mode switch routine.
 542 ! to be called just before protected mode transition
 543 
 544 default_switch:
 545         cli                     ! no interrupts allowed !
 546         mov     al,#0x80        ! disable NMI for the bootup sequence
 547         out     #0x70,al
 548         retf
 549 
 550 ! This routine only gets called, if we get loaded by the simple
 551 ! bootsect loader _and_ have a bzImage to load.
 552 ! Because there is no place left in the 512 bytes of the boot sector,
 553 ! we must emigrate to code space here.
 554 !
 555 bootsect_helper:
 556         seg cs
 557         cmp     word ptr bootsect_es,#0
 558         jnz     bootsect_second
 559         seg cs
 560         mov     byte ptr type_of_loader,#0x20
 561         mov     ax,es
 562         shr     ax,#4
 563         seg     cs
 564         mov     byte ptr bootsect_src_base+2,ah
 565         mov     ax,es
 566         seg cs
 567         mov     bootsect_es,ax
 568         sub     ax,#SYSSEG
 569         retf                    ! nothing else to do for now
 570 bootsect_second:
 571         push    cx
 572         push    si
 573         push    bx
 574         test    bx,bx   ! 64K full ?
 575         jne     bootsect_ex
 576         mov     cx,#0x8000      ! full 64K move, INT15 moves words
 577         push    cs
 578         pop     es
 579         mov     si,#bootsect_gdt
 580         mov     ax,#0x8700
 581         int     0x15
 582         jc      bootsect_panic  ! this, if INT15 fails
 583         seg cs
 584         mov     es,bootsect_es  ! we reset es to always point to 0x10000
 585         seg cs
 586         inc     byte ptr bootsect_dst_base+2
 587 bootsect_ex:
 588         seg cs
 589         mov     ah, byte ptr bootsect_dst_base+2
 590         shl     ah,4    ! we now have the number of moved frames in ax
 591         xor     al,al
 592         pop     bx
 593         pop     si
 594         pop     cx
 595         retf
 596 
 597 bootsect_gdt:
 598         .word   0,0,0,0
 599         .word   0,0,0,0
 600 bootsect_src:
 601         .word   0xffff
 602 bootsect_src_base:
 603         .byte   0,0,1                   ! base = 0x010000
 604         .byte   0x93                    ! typbyte
 605         .word   0                       ! limit16,base24 =0
 606 bootsect_dst:
 607         .word   0xffff
 608 bootsect_dst_base:
 609         .byte   0,0,0x10                ! base = 0x100000
 610         .byte   0x93                    ! typbyte
 611         .word   0                       ! limit16,base24 =0
 612         .word   0,0,0,0                 ! BIOS CS
 613         .word   0,0,0,0                 ! BIOS DS
 614 bootsect_es:
 615         .word   0
 616 
 617 bootsect_panic:
 618         push    cs
 619         pop     ds
 620         cld
 621         lea     si,bootsect_panic_mess
 622         call    prtstr
 623 bootsect_panic_loop:
 624         jmp     bootsect_panic_loop
 625 bootsect_panic_mess:
 626         .ascii  "INT15 refuses to access high mem, giving up..."
 627         db      0
 628 
 629 ! This routine checks that the keyboard command queue is empty
 630 ! (after emptying the output buffers)
 631 !
 632 ! No timeout is used - if this hangs there is something wrong with
 633 ! the machine, and we probably couldn't proceed anyway.
 634 empty_8042:
 635         call    delay
 636         in      al,#0x64        ! 8042 status port
 637         test    al,#1           ! output buffer?
 638         jz      no_output
 639         call    delay
 640         in      al,#0x60        ! read it
 641         jmp     empty_8042
 642 no_output:
 643         test    al,#2           ! is input buffer full?
 644         jnz     empty_8042      ! yes - loop
 645         ret
 646 
 647 !
 648 ! Read the cmos clock. Return the seconds in al
 649 !
 650 gettime:
 651         push    cx
 652         mov     ah,#0x02
 653         int     0x1a
 654         mov     al,dh                   ! dh contains the seconds
 655         and     al,#0x0f
 656         mov     ah,dh
 657         mov     cl,#0x04
 658         shr     ah,cl
 659         aad
 660         pop     cx
 661         ret
 662 
 663 !
 664 ! Delay is needed after doing I/O
 665 !
 666 delay:
 667         .word   0x00eb                  ! jmp $+2
 668         ret
 669 
 670 !
 671 ! Descriptor tables
 672 !
 673 
 674 gdt:
 675         .word   0,0,0,0         ! dummy
 676 
 677         .word   0,0,0,0         ! unused
 678 
 679         .word   0xFFFF          ! 4Gb - (0x100000*0x1000 = 4Gb)
 680         .word   0x0000          ! base address=0
 681         .word   0x9A00          ! code read/exec
 682         .word   0x00CF          ! granularity=4096, 386 (+5th nibble of limit)
 683 
 684         .word   0xFFFF          ! 4Gb - (0x100000*0x1000 = 4Gb)
 685         .word   0x0000          ! base address=0
 686         .word   0x9200          ! data read/write
 687         .word   0x00CF          ! granularity=4096, 386 (+5th nibble of limit)
 688 
 689 idt_48:
 690         .word   0                       ! idt limit=0
 691         .word   0,0                     ! idt base=0L
 692 
 693 gdt_48:
 694         .word   0x800           ! gdt limit=2048, 256 GDT entries
 695         .word   512+gdt,0x9     ! gdt base = 0X9xxxx
 696 
 697 !
 698 ! Include video setup & detection code
 699 !
 700 
 701 #include "video.S"
 702 
 703 !
 704 ! Setup signature -- must be last
 705 !
 706 
 707 setup_sig1:     .word   SIG1
 708 setup_sig2:     .word   SIG2
 709 
 710 !
 711 ! After this point, there is some free space which is used by the video mode
 712 ! handling code to store the temporary mode table (not used by the kernel).
 713 !
 714 
 715 modelist:
 716 
 717 .text
 718 endtext:
 719 .data
 720 enddata:
 721 .bss
 722 endbss:

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