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