I gets some unexpected data when I read a disk sector.
I tried to read disk data without a kernel, but got strange data.
I have a file fs.img
and use it like 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
Data I got:
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
Code to read sector:
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");
}
If I change the address to read, I get same output as before. If I use a text file as the disk image, I get output like below:
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
Only 0x01 and 0x37 have been changed from 0x14 to 0x02.
I have send an IDENTIFY command before reading sector. It returns unexpected data.
Data are correct if I remove calling of IDENTIFY command.
More on: https://wiki.osdev.org/ATA_PIO_Mode#IDENTIFY_command