📄 bootsect.s
字号:
/* * Copyright (c) 2005, Kohsuke Ohtani * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//*- * bootsect.s - Boot sector for FAT * * The boot sector is 512 byte code to load the OS image. It is loaded * to address 0:7c00 by POST BIOS. * The boot sector searches the target file within the root directory of * FAT file system, and loads it to predefined memory address. Then, it * jumps to the first byte of the loaded image. * * All disk access are done by using BIOS Int13h interface. The BIOS * parameter block (BPB) has the disk/FAT information, and it exists * in the first portion of the FAT boot sector. It must be filled by the * FAT format utility, or the prex kernel install utility (mkboot.com). * This program assumes that correct BPB is stored in the boot sector. * * Limitation: * - Support only FAT12/16. FAT32 is not supported. * * Memory usage: * > 3000 - 4FFF ... Disk work area * > 5000 - 6FFF ... Disk cache area * > 7000 - 7BFF ... Stack * > 7C00 - 7DFF ... This boot sector * >40000 - ... Image load address */.code16.text.align 1# Memory locations#define BOOT_STACK 0x7c00#define LOAD_ADDR 0x40000#define ENTRY_SEG 0x4000#define ENTRY_OFF 0x0000#define WORK_AREA 0x5000#define FAT_SEG 0x2000#define DATA_SEG 0x3000# FAT Directory entry#define F_NAME 0#define F_ATTR 11#define F_RESERVED 12#define F_TIME 22#define F_DATA 24#define F_CLUSTER 26#define F_SIZE 28#define DIR_SIZE 32#define DIRENT_PER_SECTOR 16# BIOS parameter block (BPB) location (%bp points to 0x7c00)#define OEM_ID 0x03(%bp)#define BYTE_PER_SECTOR 0x0b(%bp)#define SECT_PER_CLUSTER 0x0d(%bp)#define RESERVED_SECTORS 0x0e(%bp)#define NUM_OF_FATS 0x10(%bp)#define ROOT_ENTRIES 0x11(%bp)#define TOTAL_SECTORS 0x13(%bp)#define MEDIA_DESCRIPTOR 0x15(%bp)#define SECTORS_PER_FAT 0x16(%bp)#define SECTORS_PER_TRACK 0x18(%bp)#define HEADS 0x1a(%bp)#define HIDDEN_SECTORS 0x1c(%bp)#define BIG_TOTAL_SECTORS 0x20(%bp)#define PHYSICAL_DRIVE 0x24(%bp)#define EXT_BOOT_SIGNATURE 0x26(%bp)#define SERIAL_NO 0x27(%bp)#define VOLUME_ID 0x2b(%bp)#define FILE_SYS_ID 0x36(%bp)#define FILE_SYS_ID_NUM 0x3a(%bp)# Local data area (Note: These data overlaps the existing code)#define FAT_START 0x40(%bp)#define DATA_START 0x44(%bp).global _boot## Boot the system#_boot: jmp start # Skip BPB nop # Nop is for DOS compatibility## BPB# .ascii "PREX1.00".fill 0x33, 1, 0 # Drive parameter must be # filled by intaller## Setup stack and segment registers#start: cli cld # Clear direction flag xorl %eax, %eax # Set EAX to zero movw %ax, %ds movw %ax, %es movw %ax, %ss movw $BOOT_STACK, %sp movw %sp, %bp # EBP = Bios Parameter Block sti## Display message# movw $load_msg, %si movw $21, %cx call puts ## Store disk information# movl HIDDEN_SECTORS, %ebx # Get hidden sector movw RESERVED_SECTORS, %ax # Add reserved sector addl %eax, %ebx # High 16 bit of EAX is 0 movl %ebx, FAT_START # FAT start = hidden + reserved movzbw NUM_OF_FATS, %ax # Normally 2 mulw SECTORS_PER_FAT # AX = Num of sector of FATs addl %ebx, %eax # EAX = Start of root directory movw ROOT_ENTRIES, %bx shrw $4, %bx # / 16 = DIRENT_PER_SECTOR movw %bx, %cx # CX = Num of sectors for root directory addl %eax, %ebx # DATA start = FAT start + root movl %ebx, DATA_START # Start sector of data area## Find the OS image in the root directory# # EAX = Start sector of rootnext_sector: pushw %cx movl $WORK_AREA, %ebx pushw %bx call read_sector # Read 1 sector in root popw %di # DI = dir_entry movw $DIRENT_PER_SECTOR, %cx # CX = directory countnext_entry: cmpb $0, (%di) # End of dir entry ? je error # Not found testb $0x18, F_ATTR(%di) # Subdir or Volume ? jnz not_file # Skip it pusha movw $11, %cx # File name + ext = 11 byte movw $image_name, %si repe # Compare file name cmpsb popa je found_filenot_file: addw $DIR_SIZE, %di # Check next directory entry loop next_entry popw %cx loop next_sector## Error case#error: movw $err_msg, %si movw $5, %cx call putshang: hlt # Stop here jmp hang## Load image#found_file: movzwl F_CLUSTER(%di), %eax # EAX = 1st cluster of loader movl $LOAD_ADDR, %ebx # EBX = 32bit load addressload_next: call read_cluster # Read cluster of loader call next_cluster # Get next cluster# in EAX jb load_next # EOF ? ## Turn fdd motor off# movw $0x3f2, %dx xorb %al, %al outb %al, %dx## Jump to loaded image# ljmp $0x4000, $0x0## Puts - Print string## Entry:# SI - Pointer to message string# CX - Number of charactor#puts: lodsb movb $0x0e, %ah movw $0x0007, %bx int $0x10 loop puts ret## next_cluster - Return next cluster## Entry:# EAX - Current cluter### Exit:# AF - End of cluster# EAX - Next cluter### Modified:# Flags,CX,EDX,SI,DI#next_cluster: pushl %ebx movw %ax, %di # Save cluster# in DI movw $0xfff8, %si # Set default EOF to FAT16 movl %eax, %ecx shll $1, %eax # * 2 cmpb $0x36, FILE_SYS_ID_NUM # ID is 'FAT16' ? je fat_16 addl %ecx, %eax # * 3 shrl $1, %eax # / 2 movw $0xff8, %si # EOF for FAT12fat_16: # EAX - Offset of FAT entry xorw %dx, %dx divw BYTE_PER_SECTOR addl FAT_START, %eax # EAX = Sector# for FAT # DX = Offset in sector movl $WORK_AREA, %ebx pushw %bx call read_sector # Read 2 sector for border call read_sector # data popw %bx addw %dx, %bx movw (%bx), %ax cmpw $0xfff8, %si # FAT16 ? je chk_end shrw $1, %di jc odd_pos andb $0x0f, %ah jmp chk_endodd_pos: shrw $4, %axchk_end: cmpw %si, %ax popl %ebx ret## read_cluster - Read one cluster## Entry:# EBX - 32-bit pointer to buffer# EAX - Cluster number## Exit:# EBX - Point to next buffer## Modified:# flags,ECX,ECX,EDX#read_cluster: pushl %eax decw %ax # Translate clust# to sec# decw %ax xorl %ecx, %ecx movb SECT_PER_CLUSTER, %cl mull %ecx addl DATA_START, %eax # EAX = Read sec# # CX = Read sector sizeread_loop: call read_sector loop read_loop popl %eax ret## read_sector - Read one sector## Entry:# EBX - 32-bit pointer to buffer# EAX - Logical sector# to read## Exit:# EBX - Pointer to next buffer# EAX - Next sector## Modified:# Flags#read_sector: pushal pushw %ds pushw %es movl %eax, %esi # ESI = buffer movzwl SECTORS_PER_TRACK, %ecx # Get sec/track xorl %edx, %edx divl %ecx # EAX = track# # DX = sec# movw $DATA_SEG, %cx # Check in cache leaw last_data, %di cmpl DATA_START, %esi jae data_reqest movw $FAT_SEG, %cx leaw last_fat, %didata_reqest: pushal movw %cx, %es xorw %bx, %bx # ES:BX = Cache address cmpl (%di), %eax # Last track ? je hit_cache movl %eax, (%di) # Save current track# call read_trackhit_cache: popal pushw %es popw %ds shlw $9, %dx # sec# * 512 movw %dx, %si # DS:SI = Offset in cache movw %bx, %di # [EBX] -> ES:[DI] andw $0xf, %di shrl $4, %ebx movw %bx, %es mov $512, %cx # Copy 1 sector rep movsb popw %es popw %ds popal addl $512, %ebx # Next buffer incl %eax # Next sector ret## read_track - Read one track## Entry:# ES:[BX] - Pointer to buffer# EAX - Track number to read## Exit:# None## Modified:# Flags,EAX,ECX,EDX#read_track: movzwl HEADS, %ecx # Get num of head xorl %edx, %edx divl %ecx # AX = cyl# # DL = head# movb %al, %ch # CH = cyl# (low 8 bits) andb $3, %ah shlb $6, %ah orb $1, %ah movb %ah, %cl # CL[7:6] = cyl# (high 2 bits) # CL[5:0] = sec# = 1 movb %dl, %dh # DH = Head# movw SECTORS_PER_TRACK, %ax # AL = Num of sectors to read movb $2, %ah # AH = 02h (Read Disk Sectors) movb PHYSICAL_DRIVE, %dl # DL = Drive# int $0x13 # Invoke Disk BIOS jc error ret## Local Data#last_fat: .long 0xfffffffflast_data: .long 0xffffffffload_msg: .ascii "Loading "image_name: .ascii "PREXOS "crlf: .byte 0x0a, 0x0derr_msg: .ascii "Error".org 510 .word 0xaa55
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -