[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

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