Annotation of linux/boot/setup.s, revision 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.