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 
  17 INITSEG  = 0x9000       ! we move boot here - out of the way
  18 SYSSEG   = 0x1000       ! system loaded at 0x10000 (65536).
  19 SETUPSEG = 0x9020       ! this is the current segment
  20 
  21 .globl begtext, begdata, begbss, endtext, enddata, endbss
  22 .text
  23 begtext:
  24 .data
  25 begdata:
  26 .bss
  27 begbss:
  28 .text
  29 
  30 entry start
  31 start:
  32 
  33 ! ok, the read went well so we get current cursor position and save it for
  34 ! posterity.
  35 
  36         mov     ax,#INITSEG     ! this is done in bootsect already, but...
  37         mov     ds,ax
  38         mov     ah,#0x03        ! read cursor pos
  39         xor     bh,bh
  40         int     0x10            ! save it in known place, con_init fetches
  41         mov     [0],dx          ! it from 0x90000.
  42 
  43 ! Get memory size (extended mem, kB)
  44 
  45         mov     ah,#0x88
  46         int     0x15
  47         mov     [2],ax
  48 
  49 ! Get video-card data:
  50 
  51         mov     ah,#0x0f
  52         int     0x10
  53         mov     [4],bx          ! bh = display page
  54         mov     [6],ax          ! al = video mode, ah = window width
  55 
  56 ! check for EGA/VGA and some config parameters
  57 
  58         mov     ah,#0x12
  59         mov     bl,#0x10
  60         int     0x10
  61         mov     [8],ax
  62         mov     [10],bx
  63         mov     [12],cx
  64 
  65 ! Get hd0 data
  66 
  67         mov     ax,#0x0000
  68         mov     ds,ax
  69         lds     si,[4*0x41]
  70         mov     ax,#INITSEG
  71         mov     es,ax
  72         mov     di,#0x0080
  73         mov     cx,#0x10
  74         rep
  75         movsb
  76 
  77 ! Get hd1 data
  78 
  79         mov     ax,#0x0000
  80         mov     ds,ax
  81         lds     si,[4*0x46]
  82         mov     ax,#INITSEG
  83         mov     es,ax
  84         mov     di,#0x0090
  85         mov     cx,#0x10
  86         rep
  87         movsb
  88 
  89 ! Check that there IS a hd1 :-)
  90 
  91         mov     ax,#0x01500
  92         mov     dl,#0x81
  93         int     0x13
  94         jc      no_disk1
  95         cmp     ah,#3
  96         je      is_disk1
  97 no_disk1:
  98         mov     ax,#INITSEG
  99         mov     es,ax
 100         mov     di,#0x0090
 101         mov     cx,#0x10
 102         mov     ax,#0x00
 103         rep
 104         stosb
 105 is_disk1:
 106 
 107 ! now we want to move to protected mode ...
 108 
 109         cli                     ! no interrupts allowed !
 110 
 111 ! first we move the system to it's rightful place
 112 
 113         mov     ax,#0x0000
 114         cld                     ! 'direction'=0, movs moves forward
 115 do_move:
 116         mov     es,ax           ! destination segment
 117         add     ax,#0x1000
 118         cmp     ax,#0x9000
 119         jz      end_move
 120         mov     ds,ax           ! source segment
 121         sub     di,di
 122         sub     si,si
 123         mov     cx,#0x8000
 124         rep
 125         movsw
 126         jmp     do_move
 127 
 128 ! then we load the segment descriptors
 129 
 130 end_move:
 131         mov     ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
 132         mov     ds,ax
 133         lidt    idt_48          ! load idt with 0,0
 134         lgdt    gdt_48          ! load gdt with whatever appropriate
 135 
 136 ! that was painless, now we enable A20
 137 
 138         call    empty_8042
 139         mov     al,#0xD1                ! command write
 140         out     #0x64,al
 141         call    empty_8042
 142         mov     al,#0xDF                ! A20 on
 143         out     #0x60,al
 144         call    empty_8042
 145 
 146 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
 147 ! we put them right after the intel-reserved hardware interrupts, at
 148 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
 149 ! messed this up with the original PC, and they haven't been able to
 150 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
 151 ! which is used for the internal hardware interrupts as well. We just
 152 ! have to reprogram the 8259's, and it isn't fun.
 153 
 154         mov     al,#0x11                ! initialization sequence
 155         out     #0x20,al                ! send it to 8259A-1
 156         .word   0x00eb,0x00eb           ! jmp $+2, jmp $+2
 157         out     #0xA0,al                ! and to 8259A-2
 158         .word   0x00eb,0x00eb
 159         mov     al,#0x20                ! start of hardware int's (0x20)
 160         out     #0x21,al
 161         .word   0x00eb,0x00eb
 162         mov     al,#0x28                ! start of hardware int's 2 (0x28)
 163         out     #0xA1,al
 164         .word   0x00eb,0x00eb
 165         mov     al,#0x04                ! 8259-1 is master
 166         out     #0x21,al
 167         .word   0x00eb,0x00eb
 168         mov     al,#0x02                ! 8259-2 is slave
 169         out     #0xA1,al
 170         .word   0x00eb,0x00eb
 171         mov     al,#0x01                ! 8086 mode for both
 172         out     #0x21,al
 173         .word   0x00eb,0x00eb
 174         out     #0xA1,al
 175         .word   0x00eb,0x00eb
 176         mov     al,#0xFF                ! mask off all interrupts for now
 177         out     #0x21,al
 178         .word   0x00eb,0x00eb
 179         out     #0xA1,al
 180 
 181 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
 182 ! need no steenking BIOS anyway (except for the initial loading :-).
 183 ! The BIOS-routine wants lots of unnecessary data, and it's less
 184 ! "interesting" anyway. This is how REAL programmers do it.
 185 !
 186 ! Well, now's the time to actually move into protected mode. To make
 187 ! things as simple as possible, we do no register set-up or anything,
 188 ! we let the gnu-compiled 32-bit programs do that. We just jump to
 189 ! absolute address 0x00000, in 32-bit protected mode.
 190 
 191         mov     ax,#0x0001      ! protected mode (PE) bit
 192         lmsw    ax              ! This is it!
 193         jmpi    0,8             ! jmp offset 0 of segment 8 (cs)
 194 
 195 ! This routine checks that the keyboard command queue is empty
 196 ! No timeout is used - if this hangs there is something wrong with
 197 ! the machine, and we probably couldn't proceed anyway.
 198 empty_8042:
 199         .word   0x00eb,0x00eb
 200         in      al,#0x64        ! 8042 status port
 201         test    al,#2           ! is input buffer full?
 202         jnz     empty_8042      ! yes - loop
 203         ret
 204 
 205 gdt:
 206         .word   0,0,0,0         ! dummy
 207 
 208         .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
 209         .word   0x0000          ! base address=0
 210         .word   0x9A00          ! code read/exec
 211         .word   0x00C0          ! granularity=4096, 386
 212 
 213         .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
 214         .word   0x0000          ! base address=0
 215         .word   0x9200          ! data read/write
 216         .word   0x00C0          ! granularity=4096, 386
 217 
 218 idt_48:
 219         .word   0                       ! idt limit=0
 220         .word   0,0                     ! idt base=0L
 221 
 222 gdt_48:
 223         .word   0x800           ! gdt limit=2048, 256 GDT entries
 224         .word   512+gdt,0x9     ! gdt base = 0X9xxxx
 225         
 226 .text
 227 endtext:
 228 .data
 229 enddata:
 230 .bss
 231 endbss:

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