|
|
1.1 ! root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.