Stupid partition table...

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
mmiikkee12
Member
Member
Posts: 38
Joined: Sat Jun 03, 2006 11:00 pm

Stupid partition table...

Post by mmiikkee12 »

I can't seem to make my code read the partition table right. I'm reading it like this:

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;
}
However, I get bogus values for the CHS values, things like 0, 170, 0. Any ideas?
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Re: Stupid partition table...

Post by JAAman »

on newer drives you cannot rely on CHS entries to have any sane values -- all disks larger than 8GB must use LBA instead of CHS to use the full disk (due to the restricted number of bits)

and even on disks smaller than 8GB, if it was formated useing a newer OS (windows95 or later) -- examine the 'FileSystemType' field -- (iirc) there are separate entries for CHS-FAT and LBA-FAT -- chances are the disk you are examining is using LBA-FAT, which uses the LBA values instead of the CHS values

iirc, the CHS values are allowed to contain junk if the LBA values are used, and the LBA entries are allowed to contain junk if the CHS values are used, so it may be hard to tell which to use
Post Reply