📄 grldrstart.s
字号:
xorw %ax, %ax movw $0x7c00, %bp#ifndef BOOTGRUB movw %ax, %ds movw $0x1fe0, %ax movw %ax, %es movw %bp, %si /* move from 0000:7c00 */ movw %bp, %di /* move to 1fe0:7c00 */ movw $0x0100, %cx /* one sector to move */ repz movsw ljmp $0x1fe0, $(1f - Entry_32 + 0x7c00)1:#endif movw %ax, %ss /* stack and BP-relative moves up, too */ leaw -0x20(%bp), %sp sti movw %dx, 0x40(%bp) /* BIOS passes drive number in DL */ pushw %ss movb $0x41, %ah movw $0x55AA, %bx int $0x13 popw %ds jc 1f /* No EBIOS */ cmpw $0xAA55, %bx jne 1f /* No EBIOS */ testb $1, %cl jz 1f /* No EBIOS */ /* EBIOS supported */ movb $0x42, (ebios_32 - 1 - Entry_32 + 0x7c00)1: pushw %ss popw %es/* figure out where FAT and DATA area starts * (modifies EAX EDX, sets fat_start and data_start variables) */ xorl %eax, %eax movl %eax, 0x44(%bp) /* init buffer status */ /* first, find fat_start */ movw 0x0e(%bp), %ax /* reserved sectors */ addl 0x1c(%bp), %eax /* hidden sectors */ movl %eax, 0x48(%bp) /* first FAT sector */ movl %eax, 0x4c(%bp) /* first data sector, initial value */ /* next, find data_start */ movl 0x10(%bp), %eax /* number of fats, no movzbl needed: the */ /* 2 words at 0x11(%bp) are 0 for fat32. */ mull 0x24(%bp) /* sectors per fat (EDX=0) */ addl %eax, 0x4c(%bp) /* first DATA sector *//* Searches for the file in the root directory. * Returns: EAX = first cluster of file */ movl 0x2c(%bp), %eax /* root dir cluster */1: pushl %eax /* save cluster */ call cluster_to_lba_32 /* EDX is sectors per cluster, EAX is sector number */ movw $(msg_BootError_32 - Entry_32 + 0x7c00), %si jc boot_error_32 /* EOC encountered */2: lesw (loadseg_off_32 - Entry_32)(%bp), %bx /* load to loadseg:0 */ call readDisk_32 xorw %di, %di /* Search for kernel file name, and find start cluster */3: movw $11, %cx movw $(filename_32 - Entry_32 + 0x7c00), %si repz cmpsb jz 1f /* note that di now is at dirent+11 */ addw $0x20, %di andw $-0x20, %di /* 0xffe0 */ cmp 0x0b(%bp), %di /* bytes per sector */ jnz 3b /* next directory entry */ decw %dx /* initially DX holds sectors per cluster */ jnz 2b /* loop over sectors in cluster */ popl %eax /* restore current cluster */ call next_cluster_32 jmp 1b /* read next cluster */#ifndef ALTERNATIVE_KERNELloadseg_off_32: .word 0 .word LOADSEG#endif1: /* kernel directory entry is found */ pushw %es:(0x14-11)(%di) /* get cluster number HI */ pushw %es:(0x1a-11)(%di) /* get cluster number LO */ popl %eax /* convert to 32bit */ xorw %bx, %bx /* read kernel at ES:BX=LOADSEG:0 *//* read kernel */2: pushl %eax call cluster_to_lba_32 /* EDX is sectors per cluster, EAX is sector number */ jnc 1f /* EOC encountered - done */#ifdef BOOTGRUB movw 0x40(%bp), %dx /* boot_drive and boot_partition */#else movb 0x40(%bp), %bl /* FreeDOS kernel uses BL, not DL, for drive */#endif ljmp *(loadseg_off_32 - Entry_32)(%bp)1: call readDisk_32 decw %dx /* initially DX holds sectors per cluster */ jnz 1b /* loop over sectors in cluster */ popl %eax call next_cluster_32 jmp 2b /* given a cluster number, find the number of the next cluster in * the FAT chain. Needs fat_start. * input: EAX - cluster * EDX = 0 * output: EAX - next cluster * EDX = undefined */next_cluster_32: pushw %es /* pushw %di */ pushw %bx /* hi word of EBX never used */#if 1 /* xorl %edx, %edx */ shll $2, %eax /* 32bit FAT */ movzwl 0x0b(%bp), %ebx /* bytes per sector */ divl %ebx /* residue is in EDX */ /* movw %dx, %di */#else shll $2, %eax /* 32bit FAT */ ;xchgw %ax, %di /* movw %ax, %di */ movw %ax, %di ;shlw $2, %di /* 32bit FAT */ pushw %cx movw 0x0b(%bp), %bx /* bytes per sector */ bsfw %bx, %cx ;decw %cx ;decw %cx decw %bx andw %bx, %di /* mask to sector size */ shrl %cl, %eax popw %cx#endif addl 0x48(%bp), %eax /* add the first FAT sector number. */ /* EAX=absolute sector number */ movw $FATSEG, %bx movw %bx, %es xorw %bx, %bx /* is it the last accessed and already buffered FAT sector? */ cmpl 0x44(%bp), %eax jz 1f movl %eax, 0x44(%bp) /* mark sector EAX as buffered */ call readDisk_32 /* read sector EAX to buffer */1:#if 1 //.byte 0x67, 0x26, 0x80, 0x62, 0x03, 0x0f addr32 andb $0x0f, %es:3(%edx) /* mask out top 4 bits */ //.byte 0x67, 0x66, 0x26, 0x8b, 0x02 addr32 movl %es:(%edx), %eax /* read next cluster number */#else andb $0x0f, %es:3(%di) /* mask out top 4 bits */ movl %es:(%di), %eax /* read next cluster number */#endif popw %bx /* popw %di */ popw %es ret/* Convert cluster number to the absolute sector number * ... or return carry if EndOfChain! Needs data_start. * input: EAX - target cluster * output: EAX - absolute sector * EDX - [bsSectPerClust] (byte) * carry clear * (if carry set, EAX/EDX unchanged, end of chain) */cluster_to_lba_32: cmpl $0x0ffffff8, %eax /* check End Of Chain */ cmc jb 1f /* carry is stored if EOC */ /* sector = (cluster-2) * clustersize + data_start */ decl %eax decl %eax movzbl 0x0d(%bp), %edx /* sectors per cluster */ pushw %dx /* only DX would change */ mull %edx /* EDX = 0 */ popw %dx addl 0x4c(%bp), %eax /* data_start */ /* here, carry is cleared (unless parameters are wrong) */1: ret/* Read a sector from disk, using LBA or CHS * input: EAX - 32-bit DOS sector number * ES:BX - destination buffer * (will be filled with 1 sector of data) * output: ES:BX points one byte after the last byte read. * EAX - next sector */ readDisk_32: pushal xorl %edx, %edx /* EDX:EAX = LBA */ pushl %edx /* hi 32bit of sector number */ pushl %eax /* lo 32bit of sector number */ pushw %es /* buffer segment */ pushw %bx /* buffer offset */ pushw $1 /* 1 sector to read */ pushw $16 /* size of this parameter block */ xorl %ecx, %ecx pushl 0x18(%bp) /* lo:sectors per track, hi:number of heads */ popw %cx /* ECX = sectors per track */ divl %ecx /* residue is in EDX */ /* quotient is in EAX */ incw %dx /* sector number in DL */ popw %cx /* ECX = number of heads */ pushw %dx /* push sector number into stack */ xorw %dx, %dx /* EDX:EAX = cylinder * TotalHeads + head */ divl %ecx /* residue is in EDX, head number */ /* quotient is in EAX, cylinder number */ xchgb %dl, %dh /* head number should be in DH */ /* DL = 0 */ popw %cx /* pop sector number from stack */ xchgb %al, %ch /* lo 8bit cylinder should be in CH */ /* AL = 0 */ shlb $6, %ah /* hi 2bit cylinder ... */ orb %ah, %cl /* ... should be in CL */ movw $0x201, %ax /* read 1 sector */ebios_32: /* ebios_32 - 1 points to 0x02 that can be changed to 0x42 */ movw %sp, %si /* DS:SI points to disk address packet */ movb 0x40(%bp), %dl /* hard disk drive number */ pushw %es pushw %ds int $0x13 popw %ds popw %es popaw /* remove parameter block from stack */ popal jc disk_error_32 /* disk read error, jc 1f if caller handles */ incl %eax /* next sector */ addw 0x0b(%bp), %bx /* bytes per sector */ jnc 1f /* 64K bound check */ pushw %dx movw %es, %dx addb $0x10, %dh /* add 1000h to ES */ /* here, carry is cleared */ movw %dx, %es popw %dx1: /* carry stored on disk read error */ ret// . = . - (. - readDisk_32)/91msg_DiskReadError_32: .ascii "disk error\0"msg_BootError_32: .ascii "No "filename_32:#ifdef BOOTGRUB .ascii "GRLDR \0"#else .ascii "KERNEL SYS\0"#endif#ifdef ALTERNATIVE_KERNELfilename_end_32: . = Entry_32 + 0x1e8loadseg_off_32: .word 0 .word LOADSEG . = Entry_32 + 0x1ecboot_image_ofs_32: .word (filename_32 - Entry_32)+(filename_end_32 - filename_32 - 1)*2048#endif . = Entry_32 + 0x1eedisk_error_32: movw $(msg_DiskReadError_32 - Entry_32 + 0x7c00), %siboot_error_32:/* prints string DS:SI (modifies AX BX SI) *///print_32:1: lodsb (%si), %al /* get token */ //xorw %bx, %bx /* video page 0 */ movb $0x0e, %ah /* print it */ int $0x10 /* via TTY mode */ cmpb $0, %al /* end of string? */ jne 1b /* until done */ /* The caller will change this to * ljmp $0x9400, $(try_next_partition - _start1) */1: jmp 1b . = Entry_32 + 0x1fc .word 0, 0xAA55 /* Win9x uses all 4 bytes as magic value here */ . = Entry_32 + 0x200 . = _start1 + 0x600 //.arch i8086, nojumps .arch i186, nojumps/* * The following is based on FreeDOS, modified heavily by Tinybit in Feb, 2004 * * Merges FAT12 and FAT16 boot sectors to ONE FAT boot sector! * * Memory layout for GRLDR FAT single stage boot process: * * +--------+ * | | * |GRLDR | also used as max 128k FAT buffer * |LOADED | before GRLDR loading starts * |--------| 2000:0000 * | | * |--------| 0000:7E00 * |BOOTSECT| * |ORIGIN | * |--------| 0000:7C00 * | | * |--------| 0000:3000 * |CLUSTER | * |LIST | * |--------| 0000:2000 * | | * +--------+ *//*;; File:; boot.asm; Description:; DOS-C boot;; Copyright (c) 1997;; Svante Frey; All Rights Reserved;; This file is part of DOS-C.;; DOS-C is free software; you can redistribute it and/or; modify it under the terms of the GNU General Public License; as published by the Free Software Foundation; either version; 2, or (at your option) any later version.;; DOS-C is distributed in the hope that it will be useful, but; WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See; the GNU General Public License for more details.;; You should have received a copy of the GNU General Public; License along with DOS-C; see the file COPYING. If not,; write to the Free Software Foundation, 675 Mass Ave,; Cambridge, MA 02139, USA.;;; +--------+ 1FE0:7E00; |BOOT SEC|; |RELOCATE|; |--------| 1FE0:7C00; | |; |--------| 1FE0:3000; | CLUSTER|; | LIST |; |--------| 1FE0:2000; | |; |--------| 0000:7E00; |BOOT SEC| overwritten by max 128k FAT buffer; |ORIGIN | and later by max 134k loaded kernel; |--------| 0000:7C00; | |; |--------|; |KERNEL | also used as max 128k FAT buffer; |LOADED | before kernel loading starts; |--------| 0060:0000; | |; +--------+*/#ifdef BOOTGRUB#define LOADSEG_12_16 0x2000#define FATBUF 0x2000 /* offset of temp buffer for FAT chain */#else#define LOADSEG_12_16 0x0060#define FATBUF 0x2000 /* offset of temp buffer for FAT chain */#endifEntry_12_16: jmp 1f . = Entry_12_16 + 0x02 /* The default mode is CHS. This is for maximum compatiblity with * small-sized disks, e.g., floppies. * * Valid values are 0x90 for CHS mode, or 0x0e for LBA mode. * * If the BIOS int13 supports LBA, this byte can be safely set to 0x0e. * * Some USB BIOSes might have bugs when using CHS mode, so the format * program should set this byte to 0x0e. It seems that (generally) all * USB BIOSes have LBA support. * * If the format program does not know whether the BIOS has LBA * support, it may operate this way: * * if (partition_start + total_sectors_in_partition) exceeds the CHS * addressing ability(especially when it is greater than 1024*256*63), * the caller should set this byte to 0x0e, otherwise, set to 0x90. */ .byte 0x90 /* for CHS. Another possible value is 0x0e for LBA */ . = Entry_12_16 + 0x03#ifdef BOOTGRUB .ascii "GRLDR "#endif . = Entry_12_16 + 0x0b .word 0x200 /* bytes per sector */ . = Entry_12_16 + 0x0d .byte 1 /* sectors per cluster */ . = Entry_12_16 + 0x0e .word 1 /* reserved sectors */ . = Entry_12_16 + 0x10 .byte 2 /* number of FATs */ . = Entry_12_16 + 0x11 .word 224 /* Max dir entries */ . = Entry_12_16 + 0x13 .word 2880 /* total sectors in the filesystem */ . = Entry_12_16 + 0x15 .byte 0xf0 /* media descriptor */ . = Entry_12_16 + 0x16 .word 9 /* sectors per FAT */ . = Entry_12_16 + 0x18 .word 18 /* sectors per track */ . = Entry_12_16 + 0x1a .word 2 /* number of heads */ . = Entry_12_16 + 0x1c .long 0 /* hidden sectors */ . = Entry_12_16 + 0x20 .long 0 /* total sectors for large partitions */ . = Entry_12_16 + 0x24 /* drive number of the boot device. * This byte is ignored for read. The program will write DL onto * this byte. The caller should set drive number in DL. * We assume all BIOSes pass correct drive number in DL. * That is to say, buggy BIOSes are not supported!! */ .byte 0 . = Entry_12_16 + 0x25 /* partition number of this filesystem in the boot drive. * This byte is ignored for read. The boot code will write partition * number onto this byte. See Entry_12_16 + 0x41 below. */ .byte 0 . = Entry_12_16 + 0x26 .byte 0x29 /* extended boot signature */ . = Entry_12_16 + 0x27 .long 0x0AC4AF63 /* volume serial number */ . = Entry_12_16 + 0x2b .ascii "NO NAME " /* volume label */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -