在读取磁盘扇区时,我得到了一些意外的数据。
我试图在没有内核的情况下读取磁盘数据,但得到了奇怪的数据。我有一个文件fs.img
,并像使用qemu-system-i386 -drive file=fs.img,index=0,media=disk,format=raw,if=ide ......
一样使用它
hd fs.img
00000000 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 |................|
00000010 00 01 02 03 02 01 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00a00010 00 00 00 00 00 |.....|
00a00015
我得到的数据:
Addr 0x0: 40 14 00 10 00 00 3f 00 00 00 4d 30 30 20 20 20
Addr 0x10: 20 20 20 20 03 00 04 2e 2b 20 20 45 55 48 52 44
Addr 0x20: 53 20 20 20 20 20 20 20 20 20 20 20 20 20 20 10
Addr 0x30: 01 00 00 00 00 07 14 10 3f c0 00 10 01 00 07 07
Addr 0x40: 03 78 78 78 78 00 00 00 00 00 00 00 00 00 00 00
Addr 0x50: f0 16 21 00 00 21 00 00 3f 00 00 00 00 01 00 00
Addr 0x60: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00
Addr 0x70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Addr 0x80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Addr 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
读取扇区代码:
read_sector(0, 4, buffer);
#define ATA_BASE 0x1f0
void read_sector(uint addr, uint count, uchar *buffer) {
// FIXME: assert count <= 255
// TODO: wait for ready
uchar data;
// how many sector
data = count;
outb(ATA_BASE + 2, data);
// set addr
data = addr & 0xff;
outb(ATA_BASE + 3, data);
data = addr >> 8 & 0xff;
outb(ATA_BASE + 4, data);
data = addr >> 16 & 0xff;
outb(ATA_BASE + 5, data);
data = (addr >> 24 & 0x0f) | 0xe0;
outb(ATA_BASE + 6, data);
// read command
data = 0x20;
outb(ATA_BASE + 7, data);
// pool
data = inb(ATA_BASE + 7);
while ((data & 0x88) != 0x08) {
data = inb(ATA_BASE + 7);
}
// read data
int loop = count * 512;
ushort d;
int p = 0;
while (loop--) {
d = inw(ATA_BASE);
printf("%xs ", d);
buffer[p] = d;
p += 1;
}
printf("n");
}
若我把地址改为read,我得到的输出和以前一样。如果我使用文本文件作为磁盘映像,我会得到如下输出:
Addr 0x0: 40 02 00 10 00 00 3f 00 00 00 4d 30 30 20 20 20
Addr 0x10: 20 20 20 20 03 00 04 2e 2b 20 20 45 55 48 52 44
Addr 0x20: 53 20 20 20 20 20 20 20 20 20 20 20 20 20 20 10
Addr 0x30: 01 00 00 00 00 07 02 10 3f e0 00 10 01 00 07 07
Addr 0x40: 03 78 78 78 78 00 00 00 00 00 00 00 00 00 00 00
Addr 0x50: f0 16 21 00 00 21 00 00 3f 00 00 00 00 01 00 00
Addr 0x60: 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00
只有0x01和0x37已从0x14更改为0x02。
在读取扇区之前,我已经发送了一个IDENTITY命令。它返回意外的数据。
如果我删除IDENTIFY命令的调用,则数据是正确的。
更多信息:https://wiki.osdev.org/ATA_PIO_Mode#IDENTIFY_command