Stupid partition table...
Posted: Sat Jun 03, 2006 11:00 pm
I can't seem to make my code read the partition table right. I'm reading it like this:
However, I get bogus values for the CHS values, things like 0, 170, 0. Any ideas?
Code: Select all
//harddisk.h
typedef struct __attribute__((packed))
{
// Use the LBA values. The CHS isn't read correctly for some reason.
uint_8 active;
uint_8 start_head;
uint_8 start_sector;
uint_8 start_cylinder;
uint_8 partition_type;
uint_8 end_head;
uint_8 end_sector;
uint_8 end_cylinder;
uint_32 start_lba;
uint_32 end_lba;
} partition;
typedef struct __attribute__((packed))
{
uint_8 useless_data[446];
partition partitions[4];
uint_16 signature;
} partition_table;
typedef struct
{
partition part;
uint_8 drive;
} partition_info;
Code: Select all
#include <harddisk.h>
#include <types.h>
#define CMD_READ 0x20
#define CMD_WRITE 0x30
// NR = no retry
#define CMD_READ_NR 0x21
#define CMD_WRITE_NR 0x31
void read_sector(uint_8 drivenum, uint_16 cylinder, uint_8 sector, uint_8 head, uint_8 *buffer)
{
uint_8 drive;
uint_16 port_base;
switch (drivenum)
{
case 0:
case 1:
port_base = 0x1f0;
break;
case 2:
case 3:
port_base = 0x170;
break;
// If I ever get bored enough to add them, 0x1e8 for
// ide2 and 0x168 for ide3.
}
drive = 0xA0;
if (drivenum % 2) drive |= 0x10;
drive |= head;
// send some info to the IDE controller
// drive to read from
outportb(port_base + 6, drive);
// just one sector
outportb(port_base + 2, 1);
// sector
outportb(port_base + 3, sector);
// extract low and high bytes from cylinder number
uint_8 cyl_low = cylinder & 0xFF;
uint_8 cyl_high = (cylinder & 0xFF00) >> 8;
// ...then send them to the IDE controller
outportb(port_base + 4, cyl_low);
outportb(port_base + 5, cyl_high);
// and now send the command
outportb(port_base + 7, CMD_READ);
// wait for it to finish reading
while (inportb(port_base + 7) & 0x80) printf("waiting\n");
// now read the data in from the buffer
int i;
for (i = 0; i < 256; i++)
{
// No, I don't have the slightest clue what this does.
*(uint_16 *)(buffer + 2 * i) = inportw(port_base);
}
}
partition_info find_boot_partition(uint_8 ptype)
{
int boot_drive = -1;
int boot_partition = -1;
partition bp;
int i, j;
for (i = 0; i < 4; i++)
{
partition_table mbr;
read_sector(i, 0, 1, 0, &mbr);
for(j = 0; j < 4; j++)
{
if (mbr.partitions[i].partition_type == ptype)
{
printf("Found Popcorn partition on /device/hd%d/%d\n", i, j);
boot_drive = i;
boot_partition = j;
bp = mbr.partitions[j];
break;
}
}
// if we already found a partition, stop looking
if (boot_partition != -1)
break;
}
if (boot_partition == -1)
panic("Couldn't find a Popcorn partition!");
partition_info pi;
pi.part = bp;
pi.drive = boot_drive;
return pi;
}