[BACK]Return to bootsect.S CVS log [TXT][DIR] Up to [local] / prex / boot / i386 / utils / bootsect

Annotation of prex/boot/i386/utils/bootsect/bootsect.S, Revision 1.1

1.1     ! nbrk        1: /*-
        !             2:  * Copyright (c) 2005, Kohsuke Ohtani
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. Neither the name of the author nor the names of any co-contributors
        !            14:  *    may be used to endorse or promote products derived from this software
        !            15:  *    without specific prior written permission.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /**
        !            31:  * bootsect.s - Boot sector for FAT
        !            32:  *
        !            33:  * The boot sector is 512 byte code to load the OS image. It is loaded
        !            34:  * to address 0:7c00 by POST BIOS.
        !            35:  * The boot sector searches the target file within the root directory of
        !            36:  * FAT file system, and loads it to predefined memory address. Then, it
        !            37:  * jumps to the first byte of the loaded image.
        !            38:  *
        !            39:  * All disk access are done by using BIOS Int13h interface. The BIOS
        !            40:  * parameter block (BPB) has the disk/FAT information, and it exists
        !            41:  * in the first portion of the FAT boot sector. It must be filled by the
        !            42:  * FAT format utility, or the prex kernel install utility (mkboot.com).
        !            43:  * This program assumes that correct BPB is stored in the boot sector.
        !            44:  *
        !            45:  * Limitation:
        !            46:  *  - Support only FAT12/16. FAT32 is not supported.
        !            47:  *
        !            48:  * Memory usage:
        !            49:  *  > 5000 - 6FFF ... Disk work area
        !            50:  *  > 7000 - 7BFF ... Stack
        !            51:  *  > 7C00 - 7DFF ... This boot sector
        !            52:  *  >10000 -      ... FAT cache
        !            53:  *  >20000 -      ... Data cache
        !            54:  *  >30000 -      ... Image load address
        !            55:  */
        !            56: .code16
        !            57: .text
        !            58: .align 1
        !            59:
        !            60: # Memory locations
        !            61: #define BOOT_STACK             0x7c00
        !            62:
        !            63: #define LOAD_ADDR              0x30000
        !            64: #define ENTRY_SEG              0x3000
        !            65: #define ENTRY_OFF              0x0000
        !            66:
        !            67: #define WORK_AREA              0x5000
        !            68: #define FAT_SEG                        0x1000
        !            69: #define DATA_SEG               0x2000
        !            70:
        !            71: #define LOAD_MAX               0xA0000
        !            72:
        !            73: # FAT Directory entry
        !            74: #define F_NAME                 0
        !            75: #define F_ATTR                 11
        !            76: #define F_RESERVED             12
        !            77: #define F_TIME                 22
        !            78: #define F_DATA                 24
        !            79: #define F_CLUSTER              26
        !            80: #define F_SIZE                 28
        !            81:
        !            82: #define DIR_SIZE               32
        !            83: #define DIRENT_PER_SECTOR      16
        !            84:
        !            85: # BIOS parameter block (BPB) location (%bp points to 0x7c00)
        !            86: #define OEM_ID                 0x03(%bp)
        !            87: #define BYTE_PER_SECTOR                0x0b(%bp)
        !            88: #define SECT_PER_CLUSTER       0x0d(%bp)
        !            89: #define RESERVED_SECTORS       0x0e(%bp)
        !            90: #define NUM_OF_FATS            0x10(%bp)
        !            91: #define ROOT_ENTRIES           0x11(%bp)
        !            92: #define TOTAL_SECTORS          0x13(%bp)
        !            93: #define MEDIA_DESCRIPTOR       0x15(%bp)
        !            94: #define SECTORS_PER_FAT                0x16(%bp)
        !            95: #define SECTORS_PER_TRACK      0x18(%bp)
        !            96: #define HEADS                  0x1a(%bp)
        !            97: #define HIDDEN_SECTORS         0x1c(%bp)
        !            98: #define BIG_TOTAL_SECTORS      0x20(%bp)
        !            99: #define PHYSICAL_DRIVE         0x24(%bp)
        !           100: #define EXT_BOOT_SIGNATURE     0x26(%bp)
        !           101: #define SERIAL_NO              0x27(%bp)
        !           102: #define VOLUME_ID              0x2b(%bp)
        !           103: #define FILE_SYS_ID            0x36(%bp)
        !           104:
        !           105: #define FILE_SYS_ID_NUM                0x3a(%bp)
        !           106:
        !           107: # Local data area (Note: These data will overlap the existing code)
        !           108: #define FAT_START              0x40(%bp)
        !           109: #define DATA_START             0x44(%bp)
        !           110:
        !           111: .global _boot
        !           112:
        !           113: #
        !           114: # Boot the system
        !           115: #
        !           116: _boot:
        !           117:        jmp     start                           # Skip BPB
        !           118:        nop                                     # Nop is for DOS compatibility
        !           119:
        !           120: #
        !           121: # BPB
        !           122: #
        !           123:        .ascii  "PREX1.00"
        !           124: .fill 0x33, 1, 0                               # Drive parameter must be
        !           125:                                                # filled by intaller
        !           126:
        !           127: #
        !           128: # Setup stack and segment registers
        !           129: #
        !           130: start:
        !           131:        cli
        !           132:        cld                                     # Clear direction flag
        !           133:        xorl    %eax, %eax                      # Set EAX to zero
        !           134:        movw    %ax, %ds
        !           135:        movw    %ax, %es
        !           136:        movw    %ax, %ss
        !           137:        movw    $(BOOT_STACK), %sp
        !           138:        movw    %sp, %bp                        # EBP = Bios Parameter Block
        !           139:        sti
        !           140:
        !           141: #
        !           142: # Display boot message
        !           143: #
        !           144:        movw    $load_msg, %si
        !           145:        movw    $21, %cx
        !           146:        call    puts
        !           147:
        !           148: #
        !           149: # Store disk information
        !           150: #
        !           151:        movl    HIDDEN_SECTORS, %ebx            # Get hidden sector
        !           152:        movw    RESERVED_SECTORS, %ax           # Add reserved sector
        !           153:        addl    %eax, %ebx                      # High 16 bit of EAX is 0
        !           154:        movl    %ebx, FAT_START                 # FAT start = hidden + reserved
        !           155:
        !           156:        movzbw  NUM_OF_FATS, %ax                # Normally 2
        !           157:        mulw    SECTORS_PER_FAT                 # AX = Num of sector of FATs
        !           158:        addl    %ebx, %eax                      # EAX = Start of root directory
        !           159:
        !           160:        movw    ROOT_ENTRIES, %bx
        !           161:        shrw    $4, %bx                         # / 16 = DIRENT_PER_SECTOR
        !           162:        movw    %bx, %cx                        # CX = Num of sectors for root directory
        !           163:
        !           164:        addl    %eax, %ebx                      # DATA start = FAT start + root
        !           165:        movl    %ebx, DATA_START                # Start sector of data area
        !           166:
        !           167: #
        !           168: # Find the OS image in the root directory
        !           169: #
        !           170:                                                # EAX = Start sector of root
        !           171: next_sector:
        !           172:        pushw   %cx
        !           173:        movl    $(WORK_AREA), %ebx
        !           174:        pushw   %bx
        !           175:        call    read_sector                     # Read 1 sector in root
        !           176:        popw    %di                             # DI = dir_entry
        !           177:        movw    $(DIRENT_PER_SECTOR), %cx       # CX = directory count
        !           178: next_entry:
        !           179:        cmpb    $0, (%di)                       # End of dir entry ?
        !           180:        je      error                           # Not found
        !           181:        testb   $0x18, F_ATTR(%di)              # Subdir or Volume ?
        !           182:        jnz     not_file                        # Skip it
        !           183:        pusha
        !           184:        movw    $11, %cx                        # File name + ext = 11 byte
        !           185:        movw    $image_name, %si
        !           186:        repe                                    # Compare file name
        !           187:        cmpsb
        !           188:        popa
        !           189:        je      found_file
        !           190: not_file:
        !           191:        addw    $(DIR_SIZE), %di                # Check next directory entry
        !           192:        loop    next_entry
        !           193:        popw    %cx
        !           194:        loop    next_sector
        !           195:                                                # Fall through
        !           196: #
        !           197: # Error case
        !           198: #
        !           199: error:
        !           200:        movw    $err_msg, %si
        !           201:        movw    $5, %cx
        !           202:        call    puts
        !           203: hang:
        !           204:        hlt
        !           205:        jmp     hang                            # Stop here
        !           206:
        !           207: #
        !           208: # Load image
        !           209: #
        !           210: found_file:
        !           211:        movzwl  F_CLUSTER(%di), %eax            # EAX = 1st cluster of loader
        !           212:        movl    $(LOAD_ADDR), %ebx              # EBX = 32bit load address
        !           213: load_next:
        !           214:        call    read_cluster                    # Read cluster of loader
        !           215:        call    next_cluster                    # Get next cluster# in EAX
        !           216:        jb      load_next                       # EOF ?
        !           217:
        !           218: #
        !           219: # Turn fdd motor off
        !           220: #
        !           221:        movw    $0x3f2, %dx
        !           222:        xorb    %al, %al
        !           223:        outb    %al, %dx
        !           224:
        !           225: #
        !           226: # Jump to loaded image
        !           227: #
        !           228:        ljmp    $0x3000, $0x0
        !           229:
        !           230: #
        !           231: # Puts - Print string
        !           232: #
        !           233: # Entry:
        !           234: #   SI - Pointer to message string
        !           235: #   CX - Number of character
        !           236: #
        !           237: puts:
        !           238:        lodsb
        !           239:        movb    $0x0e, %ah
        !           240:        movw    $0x0007, %bx
        !           241:        int     $0x10
        !           242:        loop    puts
        !           243:        ret
        !           244:
        !           245: #
        !           246: # next_cluster - Return next cluster
        !           247: #
        !           248: # Entry:
        !           249: #   EAX - Current cluter#
        !           250: #
        !           251: # Exit:
        !           252: #   AF - End of cluster
        !           253: #   EAX - Next cluter#
        !           254: #
        !           255: # Modified:
        !           256: #   Flags,CX,EDX,SI,DI
        !           257: #
        !           258: next_cluster:
        !           259:        pushl   %ebx
        !           260:        movw    %ax, %di                        # Save cluster# in DI
        !           261:
        !           262:        movw    $0xfff8, %si                    # Set default EOF to FAT16
        !           263:
        !           264:        movl    %eax, %ecx
        !           265:        shll    $1, %eax                        # * 2
        !           266:
        !           267:        cmpb    $0x36, FILE_SYS_ID_NUM          # ID is 'FAT16' ?
        !           268:        je      fat_16
        !           269:        addl    %ecx, %eax                      # * 3
        !           270:        shrl    $1, %eax                        # / 2
        !           271:        movw    $0xff8, %si                     # EOF for FAT12
        !           272: fat_16:
        !           273:                                                # EAX - Offset of FAT entry
        !           274:        xorw    %dx, %dx
        !           275:        divw    BYTE_PER_SECTOR
        !           276:        addl    FAT_START, %eax                 # EAX = Sector# for FAT
        !           277:                                                # DX = Offset in sector
        !           278:        movl    $(WORK_AREA), %ebx
        !           279:        pushw   %bx
        !           280:        call    read_sector                     # Read 2 sector for border
        !           281:        call    read_sector                     # data
        !           282:        popw    %bx
        !           283:        addw    %dx, %bx
        !           284:        movw    (%bx), %ax
        !           285:        cmpw    $0xfff8, %si                    # FAT16 ?
        !           286:        je      chk_end
        !           287:
        !           288:        shrw    $1, %di
        !           289:        jc      odd_pos
        !           290:        andb    $0x0f, %ah
        !           291:        jmp     chk_end
        !           292: odd_pos:
        !           293:        shrw    $4, %ax
        !           294: chk_end:
        !           295:        cmpw    %si, %ax
        !           296:        popl    %ebx
        !           297:        ret
        !           298:
        !           299: #
        !           300: # read_cluster - Read one cluster
        !           301: #
        !           302: # Entry:
        !           303: #   EBX - 32-bit pointer to buffer
        !           304: #   EAX - Cluster number
        !           305: #
        !           306: # Exit:
        !           307: #   EBX - Point to next buffer
        !           308: #
        !           309: # Modified:
        !           310: #   flags,ECX,ECX,EDX
        !           311: #
        !           312: read_cluster:
        !           313:        pushl   %eax
        !           314:        decw    %ax                             # Translate clust# to sec#
        !           315:        decw    %ax
        !           316:        xorl    %ecx, %ecx
        !           317:        movb    SECT_PER_CLUSTER, %cl
        !           318:        mull    %ecx
        !           319:        addl    DATA_START, %eax                # EAX = Read sec#
        !           320:                                                # CX = Read sector size
        !           321: read_loop:
        !           322:        call    read_sector
        !           323:        cmpl    $(LOAD_MAX), %ebx
        !           324:        jae     error
        !           325:        loop    read_loop
        !           326:        popl    %eax
        !           327:        ret
        !           328:
        !           329: #
        !           330: # read_sector - Read one sector
        !           331: #
        !           332: # Entry:
        !           333: #   EBX - 32-bit pointer to buffer
        !           334: #   EAX - Logical sector# to read
        !           335: #
        !           336: # Exit:
        !           337: #   EBX - Pointer to next buffer
        !           338: #   EAX - Next sector
        !           339: #
        !           340: # Modified:
        !           341: #   Flags
        !           342: #
        !           343: read_sector:
        !           344:        pushal
        !           345:        pushw   %ds
        !           346:        pushw   %es
        !           347:
        !           348:        movl    %eax, %esi                      # ESI = buffer
        !           349:
        !           350:        movzwl  SECTORS_PER_TRACK, %ecx         # Get sec/track
        !           351:        xorl    %edx, %edx
        !           352:        divl    %ecx                            # EAX = track#
        !           353:                                                # DX = sec#
        !           354:        movw    $(DATA_SEG), %cx                # Check in cache
        !           355:        leaw    last_data, %di
        !           356:        cmpl    DATA_START, %esi
        !           357:        jae     data_reqest
        !           358:        movw    $(FAT_SEG), %cx
        !           359:        leaw    last_fat, %di
        !           360: data_reqest:
        !           361:                                                # CX = Cached segment
        !           362:        pushal                                  # [DI] = Cached track
        !           363:        movw    %cx, %es
        !           364:        xorw    %bx, %bx                        # ES:BX = Cache address
        !           365:        cmpl    (%di), %eax                     # Last track ?
        !           366:        je      hit_cache
        !           367:        movl    %eax, (%di)                     # Save current track#
        !           368:        call    read_track
        !           369: hit_cache:
        !           370:        popal
        !           371:
        !           372:        pushw   %es
        !           373:        popw    %ds
        !           374:
        !           375:        shlw    $9, %dx                         # sec# * 512
        !           376:        movw    %dx, %si                        # DS:SI = Offset in cache
        !           377:
        !           378:        movw    %bx, %di                        # [EBX] -> ES:[DI]
        !           379:        andw    $0xf, %di
        !           380:        shrl    $4, %ebx
        !           381:        movw    %bx, %es
        !           382:
        !           383:        mov     $512, %cx                       # Copy 1 sector
        !           384:        rep
        !           385:        movsb
        !           386:
        !           387:        popw    %es
        !           388:        popw    %ds
        !           389:        popal
        !           390:
        !           391:        addl    $512, %ebx                      # Next buffer
        !           392:        incl    %eax                            # Next sector
        !           393:        ret
        !           394:
        !           395: #
        !           396: # read_track - Read one track
        !           397: #
        !           398: # Entry:
        !           399: #   ES:[BX] - Pointer to buffer
        !           400: #   EAX            - Track number to read
        !           401: #
        !           402: # Exit:
        !           403: #   None
        !           404: #
        !           405: # Modified:
        !           406: #   Flags,EAX,ECX,EDX
        !           407: #
        !           408: read_track:
        !           409:        movzwl  HEADS, %ecx                     # Get num of head
        !           410:        xorl    %edx, %edx
        !           411:        divl    %ecx                            # AX = cyl#
        !           412:                                                # DL = head#
        !           413:
        !           414:        movb    %al, %ch                        # CH = cyl# (low 8 bits)
        !           415:        andb    $3, %ah
        !           416:        shlb    $6, %ah
        !           417:        orb     $1, %ah
        !           418:        movb    %ah, %cl                        # CL[7:6] = cyl# (high 2 bits)
        !           419:                                                # CL[5:0] = sec# = 1
        !           420:        movb    %dl, %dh                        # DH = Head#
        !           421:        movw    SECTORS_PER_TRACK, %ax          # AL = Num of sectors to read
        !           422:        movb    $2, %ah                         # AH = 02h (Read Disk Sectors)
        !           423:        movb    PHYSICAL_DRIVE, %dl             # DL = Drive#
        !           424:        int     $0x13                           # Invoke Disk BIOS
        !           425:        jc      error
        !           426:        ret
        !           427:
        !           428: #
        !           429: # Local Data
        !           430: #
        !           431: last_fat:      .long   0xffffffff
        !           432: last_data:     .long   0xffffffff
        !           433:
        !           434: load_msg:      .ascii  "Loading "
        !           435: image_name:    .ascii  "PREXOS     "
        !           436: crlf:          .byte   0x0a, 0x0d
        !           437: err_msg:       .ascii  "Error"
        !           438:
        !           439: .org   510
        !           440:                .word   0xaa55

CVSweb