Annotation of linux/boot/bootsect.S, revision 1.1

1.1     ! root        1: !
        !             2: ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
        !             3: ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
        !             4: ! versions of linux
        !             5: !
        !             6: #include <linux/config.h>
        !             7: SYSSIZE = DEF_SYSSIZE
        !             8: !
        !             9: !      bootsect.s              (C) 1991 Linus Torvalds
        !            10: !      modified by Drew Eckhardt
        !            11: !
        !            12: ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
        !            13: ! iself out of the way to address 0x90000, and jumps there.
        !            14: !
        !            15: ! It then loads 'setup' directly after itself (0x90200), and the system
        !            16: ! at 0x10000, using BIOS interrupts. 
        !            17: !
        !            18: ! NOTE! currently system is at most 8*65536 bytes long. This should be no
        !            19: ! problem, even in the future. I want to keep it simple. This 512 kB
        !            20: ! kernel size should be enough, especially as this doesn't contain the
        !            21: ! buffer cache as in minix
        !            22: !
        !            23: ! The loader has been made as simple as possible, and continuos
        !            24: ! read errors will result in a unbreakable loop. Reboot by hand. It
        !            25: ! loads pretty fast by getting whole sectors at a time whenever possible.
        !            26: 
        !            27: .globl begtext, begdata, begbss, endtext, enddata, endbss
        !            28: .text
        !            29: begtext:
        !            30: .data
        !            31: begdata:
        !            32: .bss
        !            33: begbss:
        !            34: .text
        !            35: 
        !            36: SETUPLEN = 4                           ! nr of setup-sectors
        !            37: BOOTSEG  = 0x07c0                      ! original address of boot-sector
        !            38: INITSEG  = DEF_INITSEG                 ! we move boot here - out of the way
        !            39: SETUPSEG = DEF_SETUPSEG                        ! setup starts here
        !            40: SYSSEG   = DEF_SYSSEG                  ! system loaded at 0x10000 (65536).
        !            41: ENDSEG   = SYSSEG + SYSSIZE            ! where to stop loading
        !            42: 
        !            43: ! ROOT_DEV & SWAP_DEV are now written by "build".
        !            44: ROOT_DEV = 0
        !            45: SWAP_DEV = 0
        !            46: 
        !            47: entry start
        !            48: start:
        !            49:        mov     ax,#BOOTSEG
        !            50:        mov     ds,ax
        !            51:        mov     ax,#INITSEG
        !            52:        mov     es,ax
        !            53:        mov     cx,#256
        !            54:        sub     si,si
        !            55:        sub     di,di
        !            56:        rep
        !            57:        movw
        !            58:        jmpi    go,INITSEG
        !            59: 
        !            60: go:    mov     ax,cs           
        !            61:        mov     dx,#0xfef4      ! arbitrary value >>512 - disk parm size
        !            62: 
        !            63:        mov     ds,ax
        !            64:        mov     es,ax
        !            65:        push    ax
        !            66: 
        !            67:        mov     ss,ax           ! put stack at 0x9ff00 - 12.
        !            68:        mov     sp,dx
        !            69: /*
        !            70:  *     Many BIOS's default disk parameter tables will not 
        !            71:  *     recognize multi-sector reads beyond the maximum sector number
        !            72:  *     specified in the default diskette parameter tables - this may
        !            73:  *     mean 7 sectors in some cases.
        !            74:  *
        !            75:  *     Since single sector reads are slow and out of the question,
        !            76:  *     we must take care of this by creating new parameter tables
        !            77:  *     (for the first disk) in RAM.  We will set the maximum sector
        !            78:  *     count to 18 - the most we will encounter on an HD 1.44.  
        !            79:  *
        !            80:  *     High doesn't hurt.  Low does.
        !            81:  *
        !            82:  *     Segments are as follows: ds=es=ss=cs - INITSEG,
        !            83:  *             fs = 0, gs = parameter table segment
        !            84:  */
        !            85: 
        !            86: 
        !            87:        push    #0
        !            88:        pop     fs
        !            89:        mov     bx,#0x78                ! fs:bx is parameter table address
        !            90:        seg fs
        !            91:        lgs     si,(bx)                 ! gs:si is source
        !            92: 
        !            93:        mov     di,dx                   ! es:di is destination
        !            94:        mov     cx,#6                   ! copy 12 bytes
        !            95:        cld
        !            96: 
        !            97:        rep
        !            98:        seg gs
        !            99:        movw
        !           100: 
        !           101:        mov     di,dx
        !           102:        movb    4(di),*18               ! patch sector count
        !           103: 
        !           104:        seg fs
        !           105:        mov     (bx),di
        !           106:        seg fs
        !           107:        mov     2(bx),es
        !           108: 
        !           109:        pop     ax
        !           110:        mov     fs,ax
        !           111:        mov     gs,ax
        !           112:        
        !           113:        xor     ah,ah                   ! reset FDC 
        !           114:        xor     dl,dl
        !           115:        int     0x13    
        !           116: 
        !           117: ! load the setup-sectors directly after the bootblock.
        !           118: ! Note that 'es' is already set up.
        !           119: 
        !           120: load_setup:
        !           121:        xor     dx, dx                  ! drive 0, head 0
        !           122:        mov     cx,#0x0002              ! sector 2, track 0
        !           123:        mov     bx,#0x0200              ! address = 512, in INITSEG
        !           124:        mov     ax,#0x0200+SETUPLEN     ! service 2, nr of sectors
        !           125:        int     0x13                    ! read it
        !           126:        jnc     ok_load_setup           ! ok - continue
        !           127: 
        !           128:        push    ax                      ! dump error code
        !           129:        call    print_nl
        !           130:        mov     bp, sp
        !           131:        call    print_hex
        !           132:        pop     ax      
        !           133:        
        !           134:        xor     dl, dl                  ! reset FDC
        !           135:        xor     ah, ah
        !           136:        int     0x13
        !           137:        j       load_setup
        !           138: 
        !           139: ok_load_setup:
        !           140: 
        !           141: ! Get disk drive parameters, specifically nr of sectors/track
        !           142: 
        !           143:        xor     dl,dl
        !           144:        mov     ah,#0x08                ! AH=8 is get drive parameters
        !           145:        int     0x13
        !           146:        xor     ch,ch
        !           147:        seg cs
        !           148:        mov     sectors,cx
        !           149:        mov     ax,#INITSEG
        !           150:        mov     es,ax
        !           151: 
        !           152: ! Print some inane message
        !           153: 
        !           154:        mov     ah,#0x03                ! read cursor pos
        !           155:        xor     bh,bh
        !           156:        int     0x10
        !           157:        
        !           158:        mov     cx,#9
        !           159:        mov     bx,#0x0007              ! page 0, attribute 7 (normal)
        !           160:        mov     bp,#msg1
        !           161:        mov     ax,#0x1301              ! write string, move cursor
        !           162:        int     0x10
        !           163: 
        !           164: ! ok, we've written the message, now
        !           165: ! we want to load the system (at 0x10000)
        !           166: 
        !           167:        mov     ax,#SYSSEG
        !           168:        mov     es,ax           ! segment of 0x010000
        !           169:        call    read_it
        !           170:        call    kill_motor
        !           171:        call    print_nl
        !           172: 
        !           173: ! After that we check which root-device to use. If the device is
        !           174: ! defined (!= 0), nothing is done and the given device is used.
        !           175: ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
        !           176: ! on the number of sectors that the BIOS reports currently.
        !           177: 
        !           178:        seg cs
        !           179:        mov     ax,root_dev
        !           180:        or      ax,ax
        !           181:        jne     root_defined
        !           182:        seg cs
        !           183:        mov     bx,sectors
        !           184:        mov     ax,#0x0208              ! /dev/ps0 - 1.2Mb
        !           185:        cmp     bx,#15
        !           186:        je      root_defined
        !           187:        mov     ax,#0x021c              ! /dev/PS0 - 1.44Mb
        !           188:        cmp     bx,#18
        !           189:        je      root_defined
        !           190: undef_root:
        !           191:        jmp undef_root
        !           192: root_defined:
        !           193:        seg cs
        !           194:        mov     root_dev,ax
        !           195: 
        !           196: ! after that (everyting loaded), we jump to
        !           197: ! the setup-routine loaded directly after
        !           198: ! the bootblock:
        !           199: 
        !           200:        jmpi    0,SETUPSEG
        !           201: 
        !           202: ! This routine loads the system at address 0x10000, making sure
        !           203: ! no 64kB boundaries are crossed. We try to load it as fast as
        !           204: ! possible, loading whole tracks whenever we can.
        !           205: !
        !           206: ! in:  es - starting address segment (normally 0x1000)
        !           207: !
        !           208: sread: .word 1+SETUPLEN        ! sectors read of current track
        !           209: head:  .word 0                 ! current head
        !           210: track: .word 0                 ! current track
        !           211: 
        !           212: read_it:
        !           213:        mov ax,es
        !           214:        test ax,#0x0fff
        !           215: die:   jne die                 ! es must be at 64kB boundary
        !           216:        xor bx,bx               ! bx is starting address within segment
        !           217: rp_read:
        !           218:        mov ax,es
        !           219:        cmp ax,#ENDSEG          ! have we loaded all yet?
        !           220:        jb ok1_read
        !           221:        ret
        !           222: ok1_read:
        !           223:        seg cs
        !           224:        mov ax,sectors
        !           225:        sub ax,sread
        !           226:        mov cx,ax
        !           227:        shl cx,#9
        !           228:        add cx,bx
        !           229:        jnc ok2_read
        !           230:        je ok2_read
        !           231:        xor ax,ax
        !           232:        sub ax,bx
        !           233:        shr ax,#9
        !           234: ok2_read:
        !           235:        call read_track
        !           236:        mov cx,ax
        !           237:        add ax,sread
        !           238:        seg cs
        !           239:        cmp ax,sectors
        !           240:        jne ok3_read
        !           241:        mov ax,#1
        !           242:        sub ax,head
        !           243:        jne ok4_read
        !           244:        inc track
        !           245: ok4_read:
        !           246:        mov head,ax
        !           247:        xor ax,ax
        !           248: ok3_read:
        !           249:        mov sread,ax
        !           250:        shl cx,#9
        !           251:        add bx,cx
        !           252:        jnc rp_read
        !           253:        mov ax,es
        !           254:        add ah,#0x10
        !           255:        mov es,ax
        !           256:        xor bx,bx
        !           257:        jmp rp_read
        !           258: 
        !           259: read_track:
        !           260:        pusha
        !           261:        pusha   
        !           262:        mov     ax, #0xe2e      ! loading... message 2e = .
        !           263:        mov     bx, #7
        !           264:        int     0x10
        !           265:        popa            
        !           266: 
        !           267:        mov dx,track
        !           268:        mov cx,sread
        !           269:        inc cx
        !           270:        mov ch,dl
        !           271:        mov dx,head
        !           272:        mov dh,dl
        !           273:        and dx,#0x0100
        !           274:        mov ah,#2
        !           275:        
        !           276:        push    dx                              ! save for error dump
        !           277:        push    cx
        !           278:        push    bx
        !           279:        push    ax
        !           280: 
        !           281:        int 0x13
        !           282:        jc bad_rt
        !           283:        add     sp, #8          
        !           284:        popa
        !           285:        ret
        !           286: 
        !           287: bad_rt:        push    ax                              ! save error code
        !           288:        call    print_all                       ! ah = error, al = read
        !           289:        
        !           290:        
        !           291:        xor ah,ah
        !           292:        xor dl,dl
        !           293:        int 0x13
        !           294:        
        !           295: 
        !           296:        add     sp, #10
        !           297:        popa    
        !           298:        jmp read_track
        !           299: 
        !           300: /*
        !           301:  *     print_all is for debugging purposes.  
        !           302:  *     It will print out all of the registers.  The assumption is that this is
        !           303:  *     called from a routine, with a stack frame like
        !           304:  *     dx 
        !           305:  *     cx
        !           306:  *     bx
        !           307:  *     ax
        !           308:  *     error
        !           309:  *     ret <- sp
        !           310:  *
        !           311: */
        !           312:  
        !           313: print_all:
        !           314:        mov     cx, #5          ! error code + 4 registers
        !           315:        mov     bp, sp  
        !           316: 
        !           317: print_loop:
        !           318:        push    cx              ! save count left
        !           319:        call    print_nl        ! nl for readability
        !           320:        jae     no_reg          ! see if register name is needed
        !           321:        
        !           322:        mov     ax, #0xe05 + 0x41 - 1
        !           323:        sub     al, cl
        !           324:        int     0x10
        !           325: 
        !           326:        mov     al, #0x58       ! X
        !           327:        int     0x10
        !           328: 
        !           329:        mov     al, #0x3a       ! :
        !           330:        int     0x10
        !           331: 
        !           332: no_reg:
        !           333:        add     bp, #2          ! next register
        !           334:        call    print_hex       ! print it
        !           335:        pop     cx
        !           336:        loop    print_loop
        !           337:        ret
        !           338: 
        !           339: print_nl:
        !           340:        mov     ax, #0xe0d      ! CR
        !           341:        int     0x10
        !           342:        mov     al, #0xa        ! LF
        !           343:        int     0x10
        !           344:        ret
        !           345: 
        !           346: /*
        !           347:  *     print_hex is for debugging purposes, and prints the word
        !           348:  *     pointed to by ss:bp in hexadecmial.
        !           349: */
        !           350: 
        !           351: print_hex:
        !           352:        mov     cx, #4          ! 4 hex digits
        !           353:        mov     dx, (bp)        ! load word into dx
        !           354: print_digit:
        !           355:        rol     dx, #4          ! rotate so that lowest 4 bits are used
        !           356:        mov     ah, #0xe        
        !           357:        mov     al, dl          ! mask off so we have only next nibble
        !           358:        and     al, #0xf
        !           359:        add     al, #0x30       ! convert to 0 based digit, '0'
        !           360:        cmp     al, #0x39       ! check for overflow
        !           361:        jbe     good_digit
        !           362:        add     al, #0x41 - 0x30 - 0xa  ! 'A' - '0' - 0xa
        !           363: 
        !           364: good_digit:
        !           365:        int     0x10
        !           366:        loop    print_digit
        !           367:        ret
        !           368: 
        !           369: 
        !           370: /*
        !           371:  * This procedure turns off the floppy drive motor, so
        !           372:  * that we enter the kernel in a known state, and
        !           373:  * don't have to worry about it later.
        !           374:  */
        !           375: kill_motor:
        !           376:        push dx
        !           377:        mov dx,#0x3f2
        !           378:        xor al, al
        !           379:        outb
        !           380:        pop dx
        !           381:        ret
        !           382: 
        !           383: sectors:
        !           384:        .word 0
        !           385: 
        !           386: msg1:
        !           387:        .byte 13,10
        !           388:        .ascii "Loading"
        !           389: 
        !           390: .org 506
        !           391: swap_dev:
        !           392:        .word SWAP_DEV
        !           393: root_dev:
        !           394:        .word ROOT_DEV
        !           395: boot_flag:
        !           396:        .word 0xAA55
        !           397: 
        !           398: .text
        !           399: endtext:
        !           400: .data
        !           401: enddata:
        !           402: .bss
        !           403: endbss:
        !           404: 

unix.superglobalmegacorp.com

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