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

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