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:
时间: 2024-11-12 18:24:36