BIOS 扩展 INT 13
上篇知道,通过BIOS的INT 13中断服务程序,可以访问磁盘,参数是读取扇区的起始磁道号、磁头号、扇区号,读取的扇区个数,缓冲区位置等。
由于原因:
BIOS通过USB总线(2.0的是通过EHCI USB)向USB存储设备发送UFI指令来和它进行交流的。
其中MODE SENSE Command(5AH)就是你所说的媒体介质、模式检测功能,在返回的数据包中包含了一个Media Type and Write Protect块里面有介质描述符的字节(该字节在格式化的UFI命令包中可以指定),BIOS就是根据这个来确认U盘的类型和是否有写保护等。
系统对USB存储设备访问是采用一种叫LBA的地址(目前采用的是LBA28),并没有所谓的CHS,windows、linux等访问USB存储设备的时候并不使用BIOS的INT 13H,而是通过USB总线直接发UFI命令包,采用的地址也是LBA,所以就不太存在兼容性问题。
然而U盘启动引导程序确是依靠BIOS的INT 13H来访问。
BIOS的INT 13H对U盘的支持(不一定支持),就是把INT 13H中的C、H、S参数转化成LBA地址,然而不同的BIOS设定的每道扇区数、每头柱面数并不一定相同。假设我们有个U盘在自己机子的BIOS被认成16H、512C、64S,分区格式化后,分区的开始位置为0H、1CH、1S,分区引导程序所在的LBA是0000064H,另一台机子的BIOS认成16H、1024C、32S,那么我们刚才做的那个启动盘,分区起始扇区的LBA就变成0000032H,很显然位置错了,当然启动不起来了。
BIOS对每道扇区数、每头柱面数的不同设置就是导致U盘启动不通用的根本原因。
也许你会说那么我们引导程序干脆直接使用扩展INT 13H发送LBA包,GRUB就是这种思路,可是有的BIOS并不支持U盘的扩展INT 13H功能,并且在检测的时候还会返回支持的假象-_-!!
其实386时代的硬盘也遇到这个问题,然而当时CMOS里面提供了硬盘类型参数的手动设置,再加上硬盘不是移动存储设备,所以问题就没那么明显了。
至于HDD、FDD、ZIP只是媒体介质描述的不同,并不能彻底解决CHS问题。
(来自:http://bbs.wuyou.com/forum.php?mod=viewthread&tid=127538)
BIOS设计者设计了INT 13的扩展功能,使得磁盘操作更简单、有效。
原理介绍可以参考:http://xiepeng63648789.blog.163.com/blog/static/4847149120097493827305/
我的代码:
org 07c00h
mov ax,cs
mov ds,ax
mov es,ax
mov ah,0x42
mov dl,80h
mov si,packet
sub bx,bx
int 0x13
jnc OK
mov ax,WrongMessage
mov bp,ax
mov cx,31
mov ax,01301h
mov bx,000ch
mov dl,0
int 10h
jmp $
OK:
mov ax,07e0h
mov es,ax
mov ax,0000h
mov bp,ax
mov cx,512
mov ax,01301h
mov bx,000ch
mov dl,0
int 10h
jmp $
WrongMessage: db "I am sorry. why not try again?"
packet:
packet_size: db 10h
reserved: db 00h
count: dw 0002h
bufferoff: dw 0000h
bufferseg: dw 07e0h
blockNum: dq 01h
times 510-($-$$) db 0
dw 0xaa55
先准备一个数据结构,作为中端服务程序的参数,里面指定读取扇区的起始地址(线性地址更直接、简单),扇区个数,缓冲区地址。
代码不足就是,该参数数据结构在中断调用完就没用了,相当于函数调用里面的局部变量,可以使用堆栈,在使用前把参数依次压入堆栈,中断服务程序到堆栈中去取参数,服务完后,再sp+len,使得空间仍可以继续使用。当我们不知道函数参数具体多少时,常用的技巧:
压入参数前
push bp
mov bp sp(记录当前位置)
push .....push(压入参数)
call ..(服务执行)
mov sp,bp(不管压入多少参数,SP都回到了以前的状态)
pop bp
(关于函数调用,到底压入堆栈的参数由谁处理,可以是中断处理函数,因为它自己本身知道自己用的参数个数是多少,方便处理,另外由函数的调用者用上面的办法处理,这是C语言里面的两个约定)
我的代码:
org 07c00h
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,7a00h
push bp
mov bp,sp
push 00h
push 00h
push 00h
push 00h
push 00h
push 00h
push 00h
push 02h
push 00h
push 00h
push 7eh
push 00h
push 00h
push 02h
push 00h
push 10h
mov ah,0x42
mov dl,80h
mov si,sp
int 0x13
mov sp,bp
pop bp
jnc OK
mov ax,WrongMessage
mov bp,ax
mov cx,30
mov ax,01301h
mov bx,000ch
mov dl,0
int 10h
jmp $
OK:
mov ax,7e00h
mov bp,ax
mov cx,512
mov ax,01301h
mov bx,000ch
mov dl,0
int 10h
jmp $
WrongMessage: db "I am sorry. why not try again?"
times 510-($-$$) db 0
dw 0xaa55
比较好的帖子或博客:
http://bbs.csdn.net/topics/10186108
http://www.mouseos.com/win7/int_0x13.html
http://blog.csdn.net/sunny_unix/article/details/7220162
http://zenhumany.blog.163.com/blog/static/1718066332011111224018552/
http://wenku.baidu.com/link?url=U_iF5JdqbhfHNNw7jGwvJi5e3W31AazQLeDJPY1MHi04REjnFoo3zoqLZzx4OS8g6Fp_vdOpexrcA96cle0UPmBHMhs7D91wux_c39qu92q
http://xiepeng63648789.blog.163.com/blog/static/4847149120097493827305/