0

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
stskyblade
  • 19
  • 4

1 Answers1

1

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

stskyblade
  • 19
  • 4
  • Does this break if addr is 33? for me it just returns 0 in the buffer. count is 1. $ hexdump -n 512 -s 16896 test.img 0004200 202e 2020 2020 2020 2020 1020 0000 0d0e 0004210 564c 564c 0000 0d0e 564c 0002 0000 0000 0004220 2e2e 2020 2020 2020 2020 1020 0000 0d0e 0004230 564c 564c 0000 0d0e 564c 0000 0000 0000 0004240 4554 5458 2020 2020 5854 2054 0000 0d0e 0004250 564c 564c 0000 0d0e 564c 003c 001c 0000 0004260 0000 0000 0000 0000 0000 0000 0000 0000 * 0004400 – Auxilus Feb 11 '23 at 20:18