Annotation of linux/boot/setup.sg, revision 1.1

1.1     ! root        1: /* 
        !             2:  *
        !             3:  *     setup.s         (C) 1991 Linus Torvalds
        !             4:  *
        !             5:  * setup.s is responsible for getting the system data from the BIOS,
        !             6:  * and putting them into the appropriate places in system memory.
        !             7:  * both setup.s and system has been loaded by the bootblock.
        !             8:  *
        !             9:  * This code asks the bios for memory/disk/other parameters, and
        !            10:  * puts them in a "safe" place: 0x90000-0x901FF, ie where the
        !            11:  * boot-block used to be. It is then up to the protected mode
        !            12:  * system to read them from there before the area is overwritten
        !            13:  * for buffer-blocks.
        !            14:  *
        !            15:  */
        !            16: 
        !            17: /* 
        !            18:  * NOTE! These had better be the same as in bootsect.s!
        !            19:  */
        !            20: 
        !            21: INITSEG  = 0x9000      # we move boot here - out of the way
        !            22: SYSSEG   = 0x1000      # system loaded at 0x10000 (65536).
        !            23: SETUPSEG = 0x9020      # this is the current segment
        !            24: 
        !            25: .globl begtext, begdata, begbss, endtext, enddata, endbss
        !            26: .text
        !            27: begtext:
        !            28: .data
        !            29: begdata:
        !            30: .bss
        !            31: begbss:
        !            32: .text
        !            33: 
        !            34: entry start
        !            35: start:
        !            36: 
        !            37: /* 
        !            38:  * ok, the read went well so we get current cursor position and save it for
        !            39:  * posterity.
        !            40:  */
        !            41: 
        !            42:        mov     $INITSEG,%ax    # this is done in bootsect already, but...
        !            43:        mov     %ax,%ds
        !            44:        mov     $0x03,%ah       # read cursor pos
        !            45:        xor     %bh,%bh
        !            46:        int     0x10            # save it in known place, con_init fetches
        !            47:        mov     [0],%dx         # it from 0x90000.
        !            48: 
        !            49: /* 
        !            50:  * Get memory size (extended mem, kB)
        !            51:  */
        !            52: 
        !            53:        mov     $0x88,%ah
        !            54:        int     0x15
        !            55:        mov     [2],%ax
        !            56: 
        !            57: /* 
        !            58:  * Get hd0 data
        !            59:  */
        !            60: 
        !            61:        mov     $0x0000,%ax
        !            62:        mov     %ax,%ds
        !            63:        lds     %si,[4*0x41]
        !            64:        mov     $INITSEG,%ax
        !            65:        mov     %ax,%es
        !            66:        mov     $0x0080,%di
        !            67:        mov     $0x10,%cx
        !            68:        rep
        !            69:        movsb
        !            70: 
        !            71: /* 
        !            72:  * Get hd1 data
        !            73:  */
        !            74: 
        !            75:        mov     $0x0000,%ax
        !            76:        mov     %ax,%ds
        !            77:        lds     %si,[4*0x46]
        !            78:        mov     $INITSEG,%ax
        !            79:        mov     %ax,%es
        !            80:        mov     $0x0090,%di
        !            81:        mov     $0x10,%cx
        !            82:        rep
        !            83:        movsb
        !            84: 
        !            85: /* 
        !            86:  * Check that there IS a hd1 :-)
        !            87:  */
        !            88: 
        !            89:        mov     $0x01500,%ax
        !            90:        mov     $0x81,%dl
        !            91:        int     0x13
        !            92:        jc      no_disk1
        !            93:        cmp     %ah,$3
        !            94:        je      is_disk1
        !            95: no_disk1:
        !            96:        mov     $INITSEG,%ax
        !            97:        mov     %ax,%es
        !            98:        mov     $0x0090,%di
        !            99:        mov     $0x10,%cx
        !           100:        mov     $0x00,%ax
        !           101:        rep
        !           102:        stosb
        !           103: is_disk1:
        !           104: 
        !           105: /* 
        !           106:  * now we want to move to protected mode ...
        !           107:  */
        !           108: 
        !           109:        cli                     # no interrupts allowed !
        !           110: 
        !           111: /* 
        !           112:  * first we move the system to it's rightful place
        !           113:  */
        !           114: 
        !           115:        mov     $0x0000,%ax
        !           116:        cld                     # 'direction'=0, movs moves forward
        !           117: do_move:
        !           118:        mov     %ax,%es         # destination segment
        !           119:        add     $0x1000,%ax
        !           120:        cmp     %ax,$0x9000
        !           121:        jz      end_move
        !           122:        mov     %ax,%ds         # source segment
        !           123:        sub     %di,%di
        !           124:        sub     %si,%si
        !           125:        mov     $0x8000,%cx
        !           126:        rep
        !           127:        movsw
        !           128:        jmp     do_move
        !           129: 
        !           130: /* 
        !           131:  * then we load the segment descriptors
        !           132:  */
        !           133: 
        !           134: end_move:
        !           135:        mov     $SETUPSEG,%ax   # right, forgot this at first. didn't work :-)
        !           136:        mov     %ax,%ds
        !           137:        lidt    idt_48          # load idt with 0,0
        !           138:        lgdt    gdt_48          # load gdt with whatever appropriate
        !           139: 
        !           140: /* 
        !           141:  * that was painless, now we enable A20
        !           142:  */
        !           143: 
        !           144:        call    empty_8042
        !           145:        mov     $0xD1,%al               # command write
        !           146:        out     %al,$0x64
        !           147:        call    empty_8042
        !           148:        mov     $0xDF,%al               # A20 on
        !           149:        out     %al,$0x60
        !           150:        call    empty_8042
        !           151: 
        !           152: /* 
        !           153:  * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
        !           154:  * we put them right after the intel-reserved hardware interrupts, at
        !           155:  * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
        !           156:  * messed this up with the original PC, and they haven't been able to
        !           157:  * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
        !           158:  * which is used for the internal hardware interrupts as well. We just
        !           159:  * have to reprogram the 8259's, and it isn't fun.
        !           160:  */
        !           161: 
        !           162:        mov     $0x11,%al               # initialization sequence
        !           163:        out     %al,$0x20               # send it to 8259A-1
        !           164:        .word   0x00eb,0x00eb           # jmp $+2, jmp $+2
        !           165:        out     %al,$0xA0               # and to 8259A-2
        !           166:        .word   0x00eb,0x00eb
        !           167:        mov     $0x20,%al               # start of hardware int's (0x20)
        !           168:        out     %al,$0x21
        !           169:        .word   0x00eb,0x00eb
        !           170:        mov     $0x28,%al               # start of hardware int's 2 (0x28)
        !           171:        out     %al,$0xA1
        !           172:        .word   0x00eb,0x00eb
        !           173:        mov     $0x04,%al               # 8259-1 is master
        !           174:        out     %al,$0x21
        !           175:        .word   0x00eb,0x00eb
        !           176:        mov     $0x02,%al               # 8259-2 is slave
        !           177:        out     %al,$0xA1
        !           178:        .word   0x00eb,0x00eb
        !           179:        mov     $0x01,%al               # 8086 mode for both
        !           180:        out     %al,$0x21
        !           181:        .word   0x00eb,0x00eb
        !           182:        out     %al,$0xA1
        !           183:        .word   0x00eb,0x00eb
        !           184:        mov     $0xFF,%al               # mask off all interrupts for now
        !           185:        out     %al,$0x21
        !           186:        .word   0x00eb,0x00eb
        !           187:        out     %al,$0xA1
        !           188: 
        !           189: /* 
        !           190:  * well, that certainly wasn't fun :-(. Hopefully it works, and we don't
        !           191:  * need no steenking BIOS anyway (except for the initial loading :-).
        !           192:  * The BIOS-routine wants lots of unnecessary data, and it's less
        !           193:  * "interesting" anyway. This is how REAL programmers do it.
        !           194:  *
        !           195:  * Well, now's the time to actually move into protected mode. To make
        !           196:  * things as simple as possible, we do no register set-up or anything,
        !           197:  * we let the gnu-compiled 32-bit programs do that. We just jump to
        !           198:  * absolute address 0x00000, in 32-bit protected mode.
        !           199:  */
        !           200: 
        !           201:        mov     $0x0001,%ax     # protected mode (PE) bit
        !           202:        lmsw    %ax             # This is it!
        !           203:        jmpi    0,8             # jmp offset 0 of segment 8 (%cs)
        !           204: 
        !           205: /* 
        !           206:  * This routine checks that the keyboard command queue is empty
        !           207:  * No timeout is used - if this hangs there is something wrong with
        !           208:  * the machine, and we probably couldn't proceed anyway.
        !           209:  */
        !           210: empty_8042:
        !           211:        .word   0x00eb,0x00eb
        !           212:        in      $0x64,%al       # 8042 status port
        !           213:        test    %al,$2          # is input buffer full?
        !           214:        jnz     empty_8042      # yes - loop
        !           215:        ret
        !           216: 
        !           217: gdt:
        !           218:        .word   0,0,0,0         # dummy
        !           219: 
        !           220:        .word   0x07FF          # 8Mb - limit=2047 (2048*4096=8Mb)
        !           221:        .word   0x0000          # base address=0
        !           222:        .word   0x9A00          # code read/exec
        !           223:        .word   0x00C0          # granularity=4096, 386
        !           224: 
        !           225:        .word   0x07FF          # 8Mb - limit=2047 (2048*4096=8Mb)
        !           226:        .word   0x0000          # base address=0
        !           227:        .word   0x9200          # data read/write
        !           228:        .word   0x00C0          # granularity=4096, 386
        !           229: 
        !           230: idt_48:
        !           231:        .word   0                       # idt limit=0
        !           232:        .word   0,0                     # idt base=0L
        !           233: 
        !           234: gdt_48:
        !           235:        .word   0x800           # gdt limit=2048, 256 GDT entries
        !           236:        .word   512+gdt,0x9     # gdt base = 0X9xxxx
        !           237:        
        !           238: .text
        !           239: endtext:
        !           240: .data
        !           241: enddata:
        !           242: .bss
        !           243: endbss:

unix.superglobalmegacorp.com

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