Annotation of linux/boot/setup.s, revision 1.1.1.1

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:

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.