📄 grldrstart.s
字号:
. = Entry_12_16 + 0x36 .ascii "FAT12 " /* filesystem ID *//*; bp is initialized to 7c00h%define bsOemName bp+0x03 ; OEM label%define bsBytesPerSec bp+0x0b ; bytes/sector%define bsSecPerClust bp+0x0d ; sectors/allocation unit%define bsResSectors bp+0x0e ; # reserved sectors%define bsFATs bp+0x10 ; # of fats%define bsRootDirEnts bp+0x11 ; # of root dir entries%define bsSectors bp+0x13 ; # sectors total in image%define bsMedia bp+0x15 ; media descrip: fd=2side9sec, etc...%define sectPerFat bp+0x16 ; # sectors in a fat%define sectPerTrack bp+0x18 ; # sectors/track%define nHeads bp+0x1a ; # heads%define nHidden bp+0x1c ; # hidden sectors%define nSectorHuge bp+0x20 ; # sectors if > 65536%define drive bp+0x24 ; drive number bp+0x25 ; partition number for GRLDR%define extBoot bp+0x26 ; extended boot signature%define volid bp+0x27%define vollabel bp+0x2b%define filesys bp+0x36%define RootDirSecs bp+0x26 ; # of sectors root dir uses ; (overwriting unused bytes)%define fat_start bp+0x28 ; first FAT sector ; (overwriting unused bytes)%define root_dir_start bp+0x2c ; first root directory sector ; (overwriting unused bytes)%define data_start bp+0x30 ; first data sector ; (overwriting unused bytes)%define data_clusters bp+0x34 ; # of clusters in data area ; (overwriting unused bytes) bp+0x36 ; bytes per FAT( > 0x1800 means FAT16) ; (overwriting unused bytes)*/ /* not used: [0x26] = byte 0x29 (ext boot param flag) * [0x27] = dword serial * [0x2b] = label (padded with 00, 11 bytes) * [0x36] = "FAT12" or "FAT16",32,32,32 (not used by Windows) * ([0x3e] is where FreeDOS parts start) */ . = Entry_12_16 + 0x3e1: cli cld#ifdef BOOTGRUB . = Entry_12_16 + 0x40 /* the byte at offset 0x41 stores the real partition number for read. * the format program or the caller should set it to a correct value. * For floppies, it should be 0xff, which stands for whole drive. */ movb $0xff, %dh /* boot partition number */ cmpb $0xff, %dh /* is floppy? */ jne 1f movb $0, %dl /* yes, let drive number = 0 */1:#endif xorw %ax, %ax movw $0x7c00, %bp#ifdef BOOTGRUB movw %ax, %ss /* stack and BP-relative moves up, too */ leaw -0x20(%bp), %sp sti /* after stack setup, we can use stack */ movw %dx, 0x24(%bp) /* BIOS passes drive number in DL */ pushaw /* AX=0 */ movb $0x41, %ah movw $0x55AA, %bx int $0x13 pushw %ss /* SS=0 */ popw %ds /* DS=0 */ jc 1f /* No EBIOS */ cmpw $0xAA55, %bx jne 1f /* No EBIOS */ testb $1, %cl jz 1f /* No EBIOS */ /* EBIOS supported */ movb $0x42, (ebios_12_16 - 1 - Entry_12_16 + 0x7c00)1: popaw /* AX=0 */ movw %ax, %es /* ES=0 */ /* AX=SS=DS=ES=0, BP=0x7C00 */#else movw %ax, %ds movw %bp, %si /* move from 0000:7c00 */ movw %bp, %di /* move to 1fe0:7c00 */ movb %dl, 0x24(%si) /* BIOS passes drive number in DL */// xchgw %ax, %dx /* let DX = 0 */ movw $0x1fe0, %ax movw %ax, %es movw $0x0100, %cx /* one sector to move */ repz movsw /* CX = 0 */ ljmp $0x1fe0, $(1f - Entry_12_16 + 0x7c00)1: movw %ax, %ss /* stack and BP-relative moves up, too */ leaw -0x20(%bp), %sp sti /* after stack setup, we can use stack */ pushw %ax /* AX=0x1FE0 */ movb $0x41, %ah movw $0x55AA, %bx int $0x13 popw %ds /* DS=0x1FE0 */ jc 1f /* No EBIOS */ cmpw $0xAA55, %bx jne 1f /* No EBIOS */ testb $1, %cl jz 1f /* No EBIOS */ /* EBIOS supported */ movb $0x42, (ebios_12_16 - 1 - Entry_12_16 + 0x7c00)1: xorw %ax, %ax /* AX=0 */#endif /* GET DRIVE PARMS: Calculate start of some disk areas */1:#if 0 .arch i486, nojumps movzwl 0x0e(%bp), %ebx /* reserved sectors */ addl 0x1c(%bp), %ebx /* hidden sectors */ movl %ebx, 0x28(%bp) /* ---- FAT start */ movzbl 0x10(%bp), %eax /* number of FATs */ movzwl 0x16(%bp), %ecx /* sectors per FAT */ mull %ecx /* EDX=0, EAX=total sectors for FAT */ addl %eax, %ebx movl %ebx, 0x2c(%bp) /* ---- RootDir start */ /* Calculate how many sectors the root directory occupies */ movzwl 0x0b(%bp), %ecx /* bytes per sector, should be 512 */ movzwl 0x11(%bp), %eax /* max number of RootDir entries */ shll $5, %eax /* total bytes RootDir occupies */ addl %ecx, %eax decl %eax /* xorl %edx, %edx */ /* EDX=0 */ divl %ecx /* EAX=AX=sectors for RootDir */ movw %ax, 0x26(%bp) /* sectors for RootDir */ addl %eax, %ebx movl %ebx, 0x30(%bp) /* ---- DataArea start */ . = . - (. - 1b)/66 .arch i186, nojumps#else movw 0x1c(%bp), %si /* number of hidden sectors(lo) */ movw 0x1e(%bp), %di /* number of hidden sectors(hi) */ addw 0x0e(%bp), %si /* number of reserved sectors */ adcw %ax, %di /* DI:SI = first FAT sector */ /* AX = 0 */ movw %si, 0x28(%bp) /* FAT start sector(lo) */ movw %di, 0x2a(%bp) /* FAT start sector(hi) */ //xchgw %ax, %dx /* let AX = 0 */ movb 0x10(%bp), %al /* number of FATs */ /* cbw */ mulw 0x16(%bp) /* sectors per FAT */ /* DX:AX = total number of FAT sectors */ /* DX = 0 since no too many FAT sectors */ addw %ax, %si adcw %dx, %di /* DI:SI = root directory start sector */ movw %si, 0x2c(%bp) /* root directory starting sector(lo) */ movw %di, 0x2e(%bp) /* root directory starting sector(hi) */ /* Calculate how many sectors the root directory occupies */ movw 0x0b(%bp), %bx /* bytes per sector */ movb $5, %cl /* divide BX by 32 */ shrw %cl, %bx /* BX = directory entries per sector */ movw 0x11(%bp), %ax /* max number of root dir entries */ addw %bx, %ax decw %ax /* xorw %dx, %dx */ /* assuming DX = 0 */ divw %bx /* AX = sectors per root directory */ cwd /* DX = 0 */ movw %ax, 0x26(%bp) /* number of sectors the root dir occupies */ addw %ax, %si /* DI:SI = first data sector */ adcw %dx, %di /* assuming DX = 0 */ movw %si, 0x30(%bp) /* data starting sector(lo) */ movw %di, 0x32(%bp) /* data starting sector(hi) */ . = . - (. - 1b)/63#endif#ifdef USE_TOTAL_CLUSTERS movw 0x13(%bp), %cx /* total sectors(small) */ jcxz 1f movw %cx, 0x20(%bp) /* total sectors(large)(lo) */ movw %dx, 0x22(%bp) /* total sectors(large)(hi), assuming DX = 0 */1: movw 0x20(%bp), %ax /* total sectors(large) */ movw 0x22(%bp), %bx addw 0x1c(%bp), %ax /* number of hidden sectors */ adcw 0x1e(%bp), %bx subw %si, %ax /* data starting sector */ sbbw %di, %bx /* BX:AX = total sectors in the data area */ movb 0x0d(%bp), %dl /* sectors per cluster(DH=0) */ xchgw %bx, %dx /* DX:AX = total sectors in the data area */ /* BX = sectors per cluster */ divw %bx /* AX = total clusters in the data area */ movw %ax, 0x34(%bp) /* total clusters in the data area */#else movw $0xffff, 0x36(%bp) /* bytes per FAT( > 0x1800 means FAT16) */ movw 0x16(%bp), %ax /* sectors per FAT */ mulw 0x0b(%bp) /* bytes per sector */ jc 1f movw %ax, 0x36(%bp)1:#endif /* Searches for the file in the root directory * * Returns: * AX = first cluster of file */ /* First, read the whole root directory into the temporary buffer */ movw 0x2c(%bp), %ax /* root directory starting sector(lo) */ movw 0x2e(%bp), %dx /* root directory starting sector(hi) */ movw 0x26(%bp), %cx /* number of sectors the root dir occupies */ lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx /* ES:BX = loadseg:0 */// pushw %es call readDisk_12_16 /* CX=0, AX,DX,ES changed */// popw %es lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %di /* ES:DI = loadseg:0 */ /* Search for kernel file name, and find start cluster */ /* BX=0, CX=0 */// pushw %cx// popw %di1: movw $(filename_12_16 - Entry_12_16 + 0x7c00), %si /* filename */ movb $11, %cl /* length of kernel filename */ pushw %di repz cmpsb popw %di jz 1f addw $0x20, %di /* next entry */ jz 2f /* or jc 2f, exceeding 64K */ /* if the entry begins in 0, this also ends the dir. */ cmpb %ch, %es:(%di) /* CH=0 */ jnz 1b2: movw $(msg_BootError_12_16 - Entry_12_16 + 0x7c00), %si jmp boot_error_12_16 /* fail if not found */#ifndef ALTERNATIVE_KERNELloadseg_off_12_16: .word 0loadseg_seg_12_16: .word LOADSEG_12_16#endif1:/****************************************************************************/ /* BX=0, CX=0 */ ###################################################################### # Reads the FAT chain and stores it in a temporary buffer in the # first 64KB. The FAT chain is stored an array of 16-bit cluster # numbers, ending with 0. # # The file must fit in conventional memory, so it can't be larger # than 640KB. The sector size must be at least 512 bytes, so the # FAT chain can't be larger than around 3KB. ###################################################################### /********************************************************************/ /* First, load the complete FAT into memory. The FAT can't be */ /* larger than 128KB, so it should fit in the temporary buffer. */ /********************************************************************/ pushw %es:0x1a(%di) /* save first cluster number of file */// lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx// /* ES:BX = loadseg:0 */ movw 0x16(%bp), %cx /* sectors per FAT */ movw 0x28(%bp), %ax /* FAT start sector(lo) */ movw 0x2a(%bp), %dx /* FAT start sector(hi) */ pushw %es /* ES=0x2000 */ call readDisk_12_16 /* CX=0, AX,DX,ES changed */ popw %ds /* DS=0x2000 */ popw %ax /* restore first cluster number of file */ /********************************************************************/ /* Then, extract the clusters of the file from the FAT */ /********************************************************************/ /* Set ES:DI to the temporary storage for the FAT chain */ pushw %ds /* ES=0x2000 */ pushw %ss popw %es movw $FATBUF, %di /* BX=0, CX=0 */2: stosw /* store cluster number */ movw %ax, %si /* SI = cluster number */ ////////////////////////////////////////////////////////////// // // FAT16 can occupy 128KB, so the segment must be adjusted // ////////////////////////////////////////////////////////////// popw %dx /* DX=0x2000, segment for FAT16 */ pushw %dx addw %si, %si /* multiply cluster number by two */ jnc 1f addb $0x10, %dh /* overflow. Add 0x1000 to segment value */1:#ifdef USE_TOTAL_CLUSTERS cmpw $0x0ff7, 0x34(%bp) /* total clusters in the data area */#else cmpw $0x1801, 0x36(%bp) /* bytes per FAT */#endif jnb 3f /******** FAT12 ********/ addw %ax, %si /* multiply cluster number by 3 ... */ shrw $1, %si /* ... and divide by 2 */ lodsw /* If the cluster number was even, the cluster value is now in * bits 0-11 of AX. If the cluster number was odd, the cluster * value is in bits 4-15, and must be shifted right 4 bits. If * the number was odd, CF was set in the last shift instruction. */ jnc 1f movb $4, %cl /* CL=4 */ shrw %cl, %ax1: andb $0x0f, %ah /* mask off the highest 4 bits */ cmpw $0x0ff7, %ax /* check for EOF */ jmp 4f3: /******** FAT16 ********/ movw %dx, %ds /* DS:SI points to next cluster */ lodsw /* AX = next cluster */ cmpw $0xfff7, %ax /* check for EOF */4: jbe 2b /* continue if not EOF */ /* Mark end of FAT chain with 0, so we have a single * EOF marker for both FAT12 and FAT16 systems. */ xorw %ax, %ax stosw/****************************************************************************/ /* Load the file into memory, one cluster at a time */ popw %es /* ES=0x2000 */// lesw (loadseg_off_12_16 - Entry_12_16)(%bp), %bx// /* ES:BX = loadseg:0 */ pushw %ss popw %ds /* DS=SS */ movw $FATBUF, %si /* set DS:SI to the FAT chain */1: /* CH=0 */ lodsw /* AX = next cluster to read */ subw $2, %ax /* cluster numbers start with 2 */ jc 1f /* the cluster should be 0 for EOC */ movb 0x0d(%bp), %cl /* CH=0, CX=sectors per cluster */ mulw %cx addw 0x30(%bp), %ax /* data starting sector(lo) */ adcw 0x32(%bp), %dx /* data starting sector(hi) */ /* DX:AX = first sector to read */ call readDisk_12_16 /* CX=0, AX,DX,ES changed */ jmp 1b /* read next cluster */1: /* EOC encountered - done */#ifdef BOOTGRUB movw 0x24(%bp), %dx /* boot_drive and boot_partition */#else movb 0x24(%bp), %bl /* FreeDOS kernel uses BL, not DL, for drive */#endif ljmp *(loadseg_off_12_16 - Entry_12_16)(%bp) /* boot it! *//****************************************************************************//* Read a number of sectors into memory. * * Call with: DS=SS * DX:AX = 32-bit DOS sector number * CX = number of sectors to read * ES:BX = destination buffer * * Returns: CX=0 * ES increased, BX untouched * ES:BX points one byte after the last byte read. * DX:AX = next sector number after read * All other registers preserved */ readDisk_12_16:2: pushfw pushaw xorw %cx, %cx pushw %cx /* hi word of hi dword */ pushw %cx /* lo word of hi dword */ pushw %dx /* hi word of lo dword */ pushw %ax /* lo word of lo dword */ pushw %es /* buffer segment */ pushw %bx /* buffer offset */ incw %cx pushw %cx /* 1 sector to read */ movb $16, %cl pushw %cx /* size of this parameter block */ xchgw %ax, %cx /* save AX to CX */ /* * translate sector number to BIOS parameters * * LBA = sector-1 offset in track * + head * sectPerTrack offset in cylinder * + cyl * sectPerTrack * nHeads offset in platter * */#if 1 pushw %bx pushw %dx movw 0x18(%bp), %ax /* sectors per track */ movw %ax, %bx mulw 0x1a(%bp) /* nHeads */ /* DX=0, AX=sectors per cylinder */ xchgw %ax, %cx /* restore AX from CX, and save AX to CX */ /* CX=nHeads * sectPerTrack <= 256*63 */ /* AX=LBA lo word */ popw %dx /* DX:AX=LBA */#else pushw %bx movw 0x18(%bp), %ax /* sectors per track */ movw %ax, %bx mulb 0x1a(%bp) /* nHeads, but maybe a word value 0x100 */ jnz 1f movb %bl, %ah /* nHeads=0x100, so AX=sectPerTrack*0x100 */1: xchgw %ax, %cx /* restore AX from CX, and save AX to CX */ /* DX:AX = LBA, CX = nHeads * sectPerTrack <= 256*63 */#endif divw %cx /* AX = cyl, DX = sector-1 + head * sectPerTrack */ xchgw %ax, %dx /* DX = cyl, AX = sector-1 + head * sectPerTrack */ divb %bl /* sectors per track */ /* DX = cyl, AL = head, AH = sector-1 */#if 1 xchgb %al, %ah /* DX = cyl, AH = head, AL = sector-1 */ incw %ax /* DX = cyl, AH = head, AL = sector */ xchgw %ax, %dx /* AX = cyl, DH = head, DL = sector */ xchgw %ax, %cx /* CX = cyl, DH = head, DL = sector */ xchgb %cl, %ch /* set cyl number low 8 bits in CH */ rorb $1, %cl /* move cyl high bits into bits 7-6 */ rorb $1, %cl /* (assumes top = 0) */ orb %dl, %cl /* merge sector into cylinder */#else movw %dx, %cx /* CX = cyl, AL = head, AH = sector-1 */ /* * the following manipulations are necessary in order to properly place * parameters into registers. * CH = cylinder number low 8 bits * CL<7-6> = cylinder high two bits * CL<5-0> = sector */ movb %al, %dh /* save head into DH for BIOS */ xchgb %cl, %ch /* set cyl number low 8 bits in CH */ rorb $1, %cl /* move cyl high bits into bits 7-6 */ rorb $1, %cl /* (assumes top = 0) */ incb %ah /* AH = sector number */ orb %ah, %cl /* merge sector into cylinder */#endif popw %bx movw $0x0201, %ax /* read 1 sector */ebios_12_16: /* ebios_12_16 - 1 points to 0x02 that can be c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -