📄 grub-0.97-patch4-emulation
字号:
+ addw $14, %sp /* adjust SP */+ popw %si+ testb $1, -14(%bp) /* lowest bit of S_count */+ popw %bp+ popl %eax+ jnz 1f+ /* read only */+ movb $0x03, %ah /* signal write protection */+ stc /* signal error */+ lret $2 /* far return discard the original flags */+1:+ /* fake write */+ xorb %ah, %ah /* signal write succeeded */+ /*clc*/ /* signal success, CF already cleared by XOR */+ lret $2 /* far return discard the original flags */+++drive_emulation:+ movw -4(%bp), %ax /* AL=Hmax, AH=Smax */+ testb $63, %ah /* disable CHS? */+ jz 2f /* yes, call restricted map */+ testb $0xc0, %ah /* readonly or disable LBA? */+ jz 1f+2:+ call restricted_map+1:+ movw 2(%bp), %ax /* get original AX */++ testb %ah, %ah /* reset disk system, always succeed */+ jnz 1f+ clc+ jmp int13_return+1:+ cmpb $0x01, %ah /* get status of last operation, always succeed */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x04, %ah /* verify sectors, always succeed */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x09, %ah /* INITIALIZE CONTROLLER WITH DRIVE PARAMETERS */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x0c, %ah /* SEEK TO CYLINDER */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x0d, %ah /* reset hard disks */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x10, %ah /* check if drive ready */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x11, %ah /* recalibrate drive */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x14, %ah /* CONTROLLER INTERNAL DIAGNOSTIC */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x05, %ah /* format track */+ jnz 1f+ xorb %ah, %ah /* do nothing but return success */+ clc+ jmp int13_return+1:+ cmpb $0x08, %ah /* get drive parameters */+ jnz 1f+ pushw %ds+ xorw %ax, %ax+ movw %ax, %ds+ testb %dl, %dl /* hard drive? */+ movb 0x475, %dl /* DL=number of hard drives */+ js 2f /* yes, jump */+ movw $0x10, %bx /* for floppy, refer to function 0x48 */+ movb 0x410, %al+ rorb $1, %al+ cbw+ shlb $1, %al+ shrb $6, %al+ incw %ax+ andb %ah, %al+ xchgw %ax, %dx /* DL=number of floppy drives */+ lesw 0x0078, %di /* point to int1E floppy parameters */+2:+ popw %ds+ movw -4(%bp), %ax /* AL=Hmax, AH=Smax */+ movb %al, %dh /* max head number */+ andb $63, %ah+ movb %ah, %cl /* max sector number */++ ///* simply use 1024 cylinders, hope this would work well */+ //orw $0xffc0, %cx /* max cylinder number=1023 */++ /* max cylinder number */++ pushl %edx+ pushl %ecx+ movzbl %dh, %eax+ movzbl %cl, %ecx+ incl %eax+ mull %ecx /* EDX=0, EAX=sectors per cylinder */+ xchgl %eax, %ecx++ movl -14(%bp), %eax /* S_count */+ andb $0xfe, %al+ decl %eax+ //xorl %edx, %edx+ divl %ecx /* EAX=max cylinder number */+ popl %ecx+ popl %edx++ movb %al, %ch /* low 8 bits of cylinder */+ shlb $6, %ah /* high 2 bits of cylinder */+ orb %ah, %cl++ //movb $0x08, %dl /* drives=8(HDs=8 as well as FDs=8) */+ xorw %ax, %ax+ clc+ jmp int13_return+1:+ cmpb $0x15, %ah /* get disk type */+ jnz 1f+ testb %dl, %dl /* hard drive? */+ js 2f /* yes, jump */+ movb $0x02, %ah /* floppy (or other removable drive) with change-line support */+ clc+ jmp int13_return+2:+ movb $0x03, %ah /* hard disk */++ /* CX:DX=total number of sectors */+ movw -14(%bp), %dx /* lo word of S_count */+ movw -16(%bp), %cx /* hi word of S_count */+ andb $0xfe, %dl+ clc+ jmp int13_return+1:+ cmpb $0x16, %ah+ jnz 1f+ xorb %ah, %ah /* AH=0 means disk not changed */+ /* clc */ /* signal success, CF already cleared by XOR */+ jmp int13_return+1:+ cmpb $0x17, %ah /* set floppy type for format */+ jnz 1f+ movb $0x03, %al /* 1.44M drive, 1.44M floppy */+ xorb %ah, %ah+ /* clc */ /* signal success, CF already cleared by XOR */+ jmp int13_return+1:+ cmpb $0x18, %ah /* set media type for format */+ jnz 1f+ testb %dl, %dl /* hard drive? */+ js 2f /* yes, jump */+ pushw %ax+ xorw %ax, %ax+ movw %ax, %es+ movw $0x0078, %di+ movl %es:(%di), %eax+ movw %ax, %di+ shrl $0x10, %eax+ movw %ax, %es+ popw %ax+ xorb %ah, %ah+ /* clc */ /* signal success, CF already cleared by XOR */+ jmp int13_return+2:+ movb $1, %ah /* temp disabled for hard disks */+ stc+ jmp int13_return+1:+ /* Now AH is neither 0 nor 1 */+ testb $0xfc, %ah /* CHS read/write sectors */+ jnz 1f+ /* so AH is either 2(for read) or 3(for write) */+#if 1+ cmpw $0x0301, %ax /* is it write 1 sector? */+ jne 2f+ cmpw $0x0001, %cx /* write to cylinder 0, sector 1? */+ jne 2f+ cmpb $0x01, %dh /* write to head 0 or 1? */+ ja 2f+ /* cmpw $0xaa55, %es:0x1fe(%bx)+ je 2f */+ testb %dl, %dl+ js 3f /* protect hard disk head 0 and 1 */+ testb %dh, %dh /* write to floppy head 0? */+ jne 2f /* no, write permitted */+3:+ movb -14(%bp), %ah /* lowest byte of S_count */+ testb $1, %ah /* fake write here means safeboot */+ jz 2f /* unsafe boot allows the write */++ /* disable the write */+ addw $12, %sp /* adjust SP */+ popw %si+ popw %bp+ popl %eax+ xorb %ah, %ah /* signal write succeeded, this is a fake */+ /* clc */ /* signal success, CF already cleared by XOR */+ lret $2 /* far return discard the original flags */+ +#else+ /* debug only. locate windows 98 unidentified write to floppy */+ pushaw+ movw 8(%bp), %ax+ movw %ax, %ds+ movw 6(%bp), %si+ subw $0x0400, %si+ movw %bx, %di+ movw $0x0400, %cx+ cld+ rep+ movsw+ movw %si, %ax+ movw %di, %bx+ subw $4, %di+ stosw+ movw %bx, %ax+ stosw+ popaw+ movb $4, %al+/*3:*/+ /*hlt*/ /* invalid write to floppy, halt the machine */+ /*jmp 3b*/+#endif+2:+ cmpb $0x7F, %al /* check if sectors exceed 127 */+ ja error_01_invalid+ testb %al, %al /* read 0 sectors not allowed */+ jz error_01_invalid+ testb $63, %cl /* beginning sector number 0 is invalid */+ jz error_01_invalid+ movb -3(%bp), %ah /* AH=Smax */+ andb $63, %ah+ pushw %cx+ andb $63, %cl+ cmpb %ah, %cl /* CL should not > max sector number */+ popw %cx+ ja error_01_invalid+ movb -4(%bp), %ah+ cmpb %ah, %dh /* DH should not > max head number */+ ja error_01_invalid+ pushw %ds+ pushw %cs+ popw %ds+ movw $(EBIOS_disk_address_packet - int13_handler), %si+ movb %al, 2(%si) /* sectors */+ movw %bx, 4(%si)+ movw %es, 6(%si)+ xorl %eax, %eax+ movb %ah, 3(%si) /* sectors_hi_reserved */+ movl %eax, 12(%si)+ movb %ch, %al /* cylinder number */+ movb %cl, %ah /* CL holds higher 2 bits */+ shrb $6, %ah /* AH lower holds the 2 bits */+ /* Now AX holds the 10 bit cylinder number */+ pushl %ebx+ xorl %ebx, %ebx+ movb -4(%bp), %bl /* max head number */+ /* xorb %bh, %bh */+ incw %bx /* BX=total heads, <=256 */+ pushl %edx+ mull %ebx /* EDX:EAX=result, so EDX=0 */+ popl %edx+ xorl %ebx, %ebx+ movb %dh, %bl /* head number */+ addl %ebx, %eax+ movb -3(%bp), %bl /* Max sector number */+ andb $63, %bl+ pushl %edx+ mull %ebx /* EDX:EAX=result, so EDX=0 */+ popl %edx+ movb %cl, %bl /* sector number */+ andb $63, %bl+ decb %bl+ addl %ebx, %eax /* EAX=lo 32 bits of logical sector number */+ movl %eax, 8(%si)+ popl %ebx+ call bound_check+ testb $0xfe, %ah /* allow all or part of sectors to tranfer */+ jnz 3f+ movl -10(%bp), %eax /* StartLBA */+ addl %eax, 8(%si)+ setb 12(%si)+ movb -5(%bp), %dl /* DL=TO_DRIVE */+ movb 3(%bp), %ah /* 0x02=read, 0x03=write */+ orb $0x40, %ah /* 0x42=EXT_read, 0x43=EXT_write */+#if 1+ call real_int13_service+#else+ pushfw+ lcall *(int13_offset - int13_handler) /* call original int13 */+#endif+ jnc 4f+ /* try again using standard read/write function */+ pushaw+ pushw %es+ pushw %dx+ movb $8, %ah+ call real_int13_service+ jc 2f+ testb $63, %cl+ stc+ jz 2f+ pushw %cx //CL=sectors/track, CH=max_cylinder+ pushw %dx //DH=Hmax+ //movzbw 2(%si), %di /* sectors */+ xorl %edi, %edi+5:+ movl 8(%si), %eax+ movl 12(%si), %edx //EDX:EAX=start_LBA+ addl %edi, %eax+ adcl $0, %edx+ ////pushl %edx+ ////pushl %eax+ andl $63, %ecx+ divl %ecx // EAX = Cylinder * Htotal + Head, EDX=Sector - 1+ incw %dx+ movw %dx, %cx //sector number+ xorw %dx, %dx+ popw %bx //BH=Hmax+ movw %bx, %bp+ //movb %bh, %bl+ //movzbl %bl, %ebx+ movzbl %bh, %ebx+ incw %bx // Htotal+ divl %ebx // EAX = Cylinder, EDX=Head+ popw %bx //BL=sectors/track, BH=max_cylinder+ pushw %bx+ pushw %bp+ shrb $6, %bl+ xchgb %bl, %bh //EBX=max_cylinder+ //cmpl $1024, %eax+ //cmc+ cmpl %eax, %ebx+ //popw %bx //BL=sectors/track, BH=max_cylinder+ jb 2f+ //ECX=sector number+ //EAX=Cylinder number+ //EDX=Head number+ //BL=sectors/track, BH=max_cylinder+ xchgb %al, %ch //move cylinder low to CH+ //AL=0+ shrw $1, %ax+ shrw $1, %ax+ orb %al, %cl //move cylinder high to CL high+ xchgw %ax, %dx //move head number to AL+ popw %bp+ popw %bx+ popw %dx //drive number+ pushw %dx+ pushw %bx+ pushw %bp+ xchgb %al, %dh //move head number to DH+ movw 4(%si), %bx+ movw 6(%si), %es+ movb 3(%bp), %ah /* 0x02=read, 0x03=write */+ //movb 2(%si), %al /* sectors */+ movb $1, %al+ call real_int13_service+ jc 2f+ incw %di+ cmpw 2(%si), %di+ jnb 2f+ popw %dx+ popw %cx+ pushw %cx //CL=sectors/track, CH=max_cylinder+ pushw %dx //DH=Hmax+ jmp 5b+2:+ popw %dx+ popw %dx+ popw %dx+ popw %es+ popaw+ jc 2f /* on error need not use the bound check */+4:+ call modify_boot_sectors+ popfw /* use bound check info */+ pushfw /* dummy push, for the following dummy pop */+ jnc 4f+ movb $0x04, %ah /* sector not found */+2:+ popfw /* dummy pop */+ stc+ pushfw+4:+ movb 2(%si), %al /* number of sectors transferred */++ /* It is not safe to use POPW %DS for running in protected mode */+ popfw /* dummy pop, skip the pushed flags */+ movb -6(%bp), %dl /* restore DL(=FROM_DRIVE) */+3:+ popw %ds+ jmp int13_return+1:+ cmpb $0x41, %ah /* EBIOS installation check */+ jnz 1f+ cmpw $0x55aa, %bx+ jnz error_01_invalid+ testb %dl, %dl+ jns error_01_invalid+ movw $0xaa55, %bx+ movb $0x21, %ah /* major version 2.1(EDD-1.1) */+ movw $0x01, %cx /* support functions 42h,43h,44h,47h,48h */+ clc+ jmp int13_return+1:+ cmpb $0x42, %ah /* EBIOS read sectors */+ jz 2f+ cmpb $0x43, %ah /* EBIOS write sectors */+ jnz 1f+2:+ movw -2(%bp), %si /* get old SI, disk address packet */+ movl (%si), %eax /* packet length, sectors, etc. */+ testb %ah, %ah+ jnz error_01_invalid+ testb $0xf0, %al+ jz error_01_invalid+ shrl $16, %eax+ testw $0xff80, %ax+ jnz error_01_invalid+ call bound_check+ testb $0xfe, %ah /* allow all or part of sectors to tranfer */+ jnz int13_return+ movl -10(%bp), %eax /* StartLBA */+ addl %eax, 8(%si)+ jnc 2f+ incl 12(%si)+2:+ movb -5(%bp), %dl /* DL=TO_DRIVE */+ movb 3(%bp), %ah /* 0x42=read, 0x43=write */+#if 1+ call real_int13_service+#else+ pushfw+ lcall %cs:*(int13_offset - int13_handler) /* call original int13 */+#endif+ jc 2f /* on error need not use the bound check */+ popfw /* use bound check info */+ pushfw /* dummy push, for the following dummy pop */+ jnc 3f+ movb $0x04, %ah /* sector not found */+2:+ popfw /* dummy pop */+ stc+ pushfw+3:+#if 0+ /* this pair can be omitted */+ popfw /* dummy pop */+ pushfw+#endif+ movb -6(%bp), %dl /* restore DL(=FROM_DRIVE) */+ pushl %eax+ movl -10(%bp), %eax /* StartLBA */+ subl %eax, 8(%si)+ jnc 2f+ decl 12(%si)+2:+ popl %eax+ popfw+ jmp int13_return+1:+ cmpb $0x44, %ah /* EBIOS verify sectors */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x47, %ah /* EBIOS seek */+ jnz 1f+ xorb %ah, %ah+ clc+ jmp int13_return+1:+ cmpb $0x48, %ah /* EBIOS GET DRIVE PARAMETERS */+ jnz error_01_invalid+ movw -2(%bp), %si /* get old SI, extended drive parameter table */+ movw $26, (%si) /* buffer length */+ movw $2, 2(%si) /* info */+ xorl %eax, %eax+ movl %eax, 8(%si) /* total heads */+ movl %eax, 12(%si) /* sectors per track */+ movl %eax, 16(%si) /* total sectors */+ movl %eax, 20(%si) /* hi 32 bits of total sectors */+ pushl %ebx+ xorl %ebx, %ebx+ movw -4(%bp), %ax /* AL=Hmax, AH=Smax */+ andb $63, %ah+ movb %ah, 12(%si) /* sectors per track */+ movb %ah, %bl+ xorb %ah, %ah+ incw %ax /* total heads=Hmax+1 */+ movw %ax, 8(%si) /* total heads */+ pushl %edx+ mulw %bx /* DX:AX=product, DX=0 */+ movw %ax, %bx /* BX=sectors per cylinder */+ movl -14(%bp), %eax /* total sectors */+ andb $0xfe, %al+ movl %eax, 16(%si) /* total sectors */+ xorl %edx, %edx /* EDX:EAX=64bit total sectors */+ testw %bx, %bx+ jz 2f+ divl %ebx /* EAX=quotient, EDX=residue */+2:+ testl %edx, %edx+ popl %edx+ popl %ebx+ jz 2f+ incl %eax+2:+ movl %eax, 4(%si) /* total cylinders */+ movw $512, 24(%si) /* bytes per sector */+ xorb %ah, %ah+ /*clc*/ /* signal success, CF already cleared by XOR */+ jmp int13_return+error_01_invalid:+ movb $0x01, %ah /* unsupported function call */+ stc /* signal error */+int13_return:+ pushw %ax /* save status */+ pushfw+ popw %ax+ movw %ax, 10(%bp) /* update flags in the stack */+ movw -2(%bp), %si /* restore the original SI */+ movl 2(%bp), %eax /* restore the original EAX */+ movw (%bp), %bp /* restore the original BP */+ popw %ax /* restore status */+ addw $20, %sp /* adjust SP */+ iret++bound_check:++ /* + * check if the request exceeds the boundary of the emulated disk.+ *+ * input: DS:SI+ * output: AH=0 no restrictions, all sectors transferred+ * AH=1 sectors transferred, but not all+ * AH=4 error exit immediately, no sectors transferred+ *+ * if S_count=StartLBA=0, then no restrictions+ * else if 8(%si)>=S_count then error+ * else if 8(%si)+2(%si)<=S_count then no restrictions+ * else let 2(%si)=S_count-8(%si),call original int13,signal error+ *+ */+ movl -10(%bp), %eax /* StartLBA */+ testl %eax, %eax+ jnz 2f+ movl -14(%bp), %eax /* S_count */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -