|
本帖最后由 不点 于 2013-11-9 09:40 编辑
CDROM 驱动在哪个文件里?挂载后是否分配了 BIOS 驱动器号?客户程序如何获知并调用 CDROM?
在 int13 处理程序里(asm.S)。挂载后分配的盘号是在 0xC0 至 0xE8 之间。之所以是不确定的,是因为需要避免与 (cd) 相冲突,因为 (cd) 是 BIOS 传入的 no-emulation mode 的 CDROM 盘号,它在 0x80 至 0xFF 之间变动,它是不确定的。所以,由 cdrom --init 所建立的 (cd0), (cd1), ... (cd7) 也是不确定的。但 (cd0), (cd1), ... (cd7) 的盘号是连续分配的,比如说,它们可能是 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7;或者可能是 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7。
客户程序无需关注具体的 BIOS 盘号。用 (cd0), (cd1), ... (cd7) 来访问便可。
假如 U 盘以 80h 启动,后来使用 usb --init 挂载,加载了 usb 驱动后,原来 BIOS 的 usb 驱动就失效了。此时使用 DL=80h 的 int13 ,同样会死机。估计 find 或其他函数会探索磁盘。
即使原来的 (hd0) 失效了也没关系。失效了就不用它了。把这写入文档,一切 OK。正如我们警告用户不可以随便使用 find --set-root 那样,启用 USB 驱动之后,就不要使用原来的 USB 设备(fd0 和 hd0)了。既然新的 USB 驱动是成功的,那用户没有理由再去访问原来的 hd0 或 fd0 了。用户可以(用某条命令)把新的 USB 设备挂在 fd0 或 hd0 或任意别的盘号上。
目前的 cdrom --init 能够发现多个 CDROM 驱动器,它们分别用 (cd0), (cd1), ... (cd7) 来访问。
类似地,你的 usb --init 也可以发现多个 USB 驱动器,比如说,它们分别用 (sd0), (sd1), ... (sd7) 来访问。普通的 USB 软盘、硬盘可以支持,甚至 USB-CDROM 也是可以支持的。这里的 (sdN) 共 8 个,你可以把它们的实际盘号记录在数组变量 usb_drive[8] 中,数组的每个元素占用单字节,数组就放在 int13 处理程序开头的那些未使用的保留区域(asm.S)中。
在 cdrom --init 的情况下,(cd0), (cd1), ... (cd7) 的盘号是连续分配的。
- ENTRY(atapi_dev_count) .byte 0
- ENTRY(min_cdrom_id) .byte 0xE0
复制代码 min_cdrom_id 就对应于 (cd0),atapi_dev_count 的最大值是 8。(min_cdrom_id + atapi_dev_count - 1) 就是已经被驱动成功了的最大的 (cdN) 的 BIOS 盘号。
在 usb --init 的情况下,以上这些 cdrom 的变量都作废了。(sdN) 盘号不再连续分配,而是可以由某个命令行参数来控制的,而且在驱动建立以后,盘号也可以用某条命令来随意修改。
比方说,usb_drive[8] 数组可以放在如下的保留空间中(选择一个永远也用不着的盘号 0x3F 作为初始值):- VARIABLE(saved_pxe_mac)
- .byte 0, 0, 0, 0, 0, 0
- /* space reserved. */
- . = int13_handler + 0x130
- VARIABLE(usb_drive)
- .byte 0x3F
- .byte 0x3F
- .byte 0x3F
- .byte 0x3F
- .byte 0x3F
- .byte 0x3F
- .byte 0x3F
- .byte 0x3F
- /* space reserved. */
- . = int13_handler + 0x140
复制代码 必须放在偏移 0 至 0x140 之间,才能保证以后(在进入 DOS 而启动 grub.exe,或者当用 chainloader 启动了一个新的 grldr 时)让这些盘号的设置能够在新的 grub 环境仍然起作用。
补充一下:
鉴于 USB 启动的复杂性、困难性,可以简单地实现,不要实现得太庞大。
比如说,发现启动盘是 fd0,就把 USB 驱动的新盘也定为 fd0,发现启动盘是 hd0,就把 USB 驱动的新盘也定为 hd0。
这样做就安全了。如果发现多个 USB 设备,不要去驱动多余的设备,只驱动与启动盘相对应的 USB 设备。这样也就不需要很多个 (sdN) 了,而是只要有一个单字节变量 usb_drive 来做就够了。
usb --init 之后,默认的 usb_drive 设定为当初的启动盘 (fd0) 或 (hd0)。此后,为了灵活性,用户可以调整 usb_drive 的盘号为其他任意的盘号。
由于只需要单字节的 usb_drive 盘符,因此,可以在 int13_handler 的开头(在偏移 0 的附近处)找一个空白无用的字节来存放 usb_drive。也尽量不要覆盖掉原来的 min_cdrom_id 和 atapi_dev_count,也不要挪动它们的位置。也许有人将来想同时支持 cdrom 和 usb,因此我们就不要破坏了这样的可能性,我们要尽量提供方便,给未来的开发者留有余地。
位于偏移 0 至 0x140 的字节都是不变的,不同的 grub4dos 版本,仿真代码的开头 0x140 个字节的意义是相同的,各变量的位置是固定的,这样就保持了 grub4dos 新旧版本仿真代码中的关键数据结构的兼容性。新设计一个变量,一开始就应该把它的位置设计好,一旦确定,将来就不能动了,因为兼容性在制约着这一切。如果动了,那就破坏兼容性了。因此,设计的时候,就要注意节约,不要浪费。如果只是需要一个字节来保存 usb_drive 的值,那么目前我认为最节约的位置是在偏移 0x01 处,这里刚好保留了一个字节。这个 usb_drive 的初始值可以是 0x3F(它表示没有 usb_drive),但 usb 驱动程序初始化的时候,有可能把它改成 0x00 或 0x80,而用户也可能根据需要而把它改成别的任何一个盘号。
要有灵活性。如果用户发现 usb 驱动的存在影响了 Windows 的后续行为,导致 Windows 无法识别 usb 设备,或者出现别的故障,那么,给用户一个机会,让用户有可能在启动 Windows 之前卸载 usb 驱动。如果把 usb_drive 设置为 0x3F,那就相当于卸载了 USB 驱动。
|
|