读Linux 2.4.33.4的时候发现一个不怎么显眼的bug,位置/arch/i386/boot/bootsect.S,第271行,read_track子程序处:
read_track:
pusha
pusha
movw $0xe2e, %ax # loading... message 2e = .
movw $7, %bx
int $0x10
popa
# Accessing head, track, sread via %si gives shorter code.
movw 4(%si), %dx # 4(%si) = track
movw (%si), %cx # (%si) = sread
incw %cx
movb %dl, %ch
movw 2(%si), %dx # 2(%si) = head
movb %dl, %dh
andw $0x0100, %dx
movb $2, %ah
pushw %dx # save for error dump
pushw %cx
pushw %bx
pushw %ax
int $0x13
jc bad_rt
addw $8, %sp
popa
ret
而在bad_rt处:
bad_rt:
pushw %ax # save error code
call print_all # %ah = error, %al = read
xorb %ah, %ah
xorb %dl, %dl
int $0x13
addw $10, %sp
popa
jmp read_track
红色部分就是问题所在,如果读取一个磁道失败,程序跳转至bad_rt,复位磁盘后再次调用read_track子程序。
但注意此时会再次在屏幕上输出一个'.'。假设一个磁盘的磁道出现问题,则内核会一直在屏幕上输出'.'并且无法继续。当然这样不会有什么大的影响,不过这样做不太符合通常的逻辑,即读取失败光标应该卡住。一个比较好的方法是:
read_track:
pusha
# Accessing head, track, sread via %si gives shorter code.
movw 4(%si), %dx # 4(%si) = track
movw (%si), %cx # (%si) = sread
incw %cx
movb %dl, %ch
movw 2(%si), %dx # 2(%si) = head
movb %dl, %dh
andw $0x0100, %dx
movb $2, %ah
pushw %dx # save for error dump
pushw %cx
pushw %bx
pushw %ax
int $0x13
jc bad_rt
addw $8, %sp
movw $0xe2e, %ax # loading... message 2e = .
movw $7, %bx
int $0x10
popa
ret
'.'应该在成功读取一个磁道后才输出,而不是在其之前。
该BUG早在0.12版就已经有了!!,不过在最新的2.6系列内核中,因为不再支持从软盘引导,这部分代码已经被移除。