void PartitionHandle::CheckEBR(u8 PartNum, sec_t ebr_lba)
{
	EXTENDED_BOOT_RECORD *ebr = (EXTENDED_BOOT_RECORD*)MEM2_alloc(MAX_BYTES_PER_SECTOR);
	if(ebr == NULL)
		return;
	sec_t next_erb_lba = 0;

	do
	{
		// Read and validate the extended boot record
		if(!interface->readSectors(ebr_lba + next_erb_lba, 1, ebr))
		{
			MEM2_free(ebr);
			return;
		}
		if(ebr->signature != EBR_SIGNATURE && ebr->signature != EBR_SIGNATURE_MOD)
		{
			MEM2_free(ebr);
			return;
		}

		if(le32(ebr->partition.block_count) > 0 && !IsExisting(ebr_lba + next_erb_lba + le32(ebr->partition.lba_start)))
		{
			AddPartition(PartFromType(ebr->partition.type), ebr_lba + next_erb_lba + le32(ebr->partition.lba_start),
					le32(ebr->partition.block_count), (ebr->partition.status == PARTITION_BOOTABLE), ebr->partition.type, PartNum);
		}
		// Get the start sector of the current partition
		// and the next extended boot record in the chain
		next_erb_lba = le32(ebr->next_ebr.lba_start);
	}
	while(next_erb_lba > 0);

	MEM2_free(ebr);
}
void PartitionHandle::CheckEBR(int PartNum, sec_t ebr_lba)
{
	EXTENDED_BOOT_RECORD *ebr = (EXTENDED_BOOT_RECORD *) malloc(MAX_SECTOR_SIZE);
	if(!ebr)
		return;

	sec_t next_erb_lba = 0;

	do
	{
		// Read and validate the extended boot record
		if (!interface->readSectors(ebr_lba + next_erb_lba, 1, ebr))
			break;

		if (ebr->signature != EBR_SIGNATURE)
			break;

		PARTITION_RECORD * partition = (PARTITION_RECORD *) &ebr->partition;

		if(le32(partition->block_count) > 0)
		{
			AddPartition(PartFromType(partition->type), ebr_lba + next_erb_lba + le32(partition->lba_start),
						 le32(partition->block_count), (partition->status == PARTITION_BOOTABLE),
						 partition->type, PartNum, ebr_lba + next_erb_lba);
		}
		// Get the start sector of the current partition
		// and the next extended boot record in the chain
		next_erb_lba = le32(ebr->next_ebr.lba_start);
	}
	while(next_erb_lba > 0);

	free(ebr);
}
void PartitionHandle::AddPartition(const char *name, u64 lba_start, u64 sec_count, bool bootable, u8 part_type, u8 part_num)
{
	u8 *buffer = (u8*)MEM2_alloc(MAX_BYTES_PER_SECTOR);
	if(buffer == NULL)
		return;

	if(!interface->readSectors(lba_start, 1, buffer))
	{
		MEM2_free(buffer);
		return;
	}

	wbfs_head_t *head = (wbfs_head_t*)buffer;

	if(head->magic == wbfs_htonl(WBFS_MAGIC))
	{
		name = "WBFS";
		part_type = 0xBF;   //Override partition type on WBFS
		//! correct sector size in physical sectors (512 bytes per sector)
		sec_count = (u64) head->n_hd_sec * (u64) (1 << head->hd_sec_sz_s) / (u64) BYTES_PER_SECTOR;
	}
	else if(*((u16 *)(buffer + 0x1FE)) == 0x55AA)
	{
		//! Partition type can be missleading the correct partition format. Stupid lazy ass Partition Editors.
		if((memcmp(buffer + 0x36, "FAT", 3) == 0 || memcmp(buffer + 0x52, "FAT", 3) == 0) &&
			strncmp(PartFromType(part_type), "FAT", 3) != 0)
		{
			name = "FAT32";
			part_type = 0x0c;
		}
		if(memcmp(buffer + 0x03, "NTFS", 4) == 0)
		{
			name = "NTFS";
			part_type = 0x07;
		}
	}

	PartitionFS PartitionEntry;
	PartitionEntry.FSName = name;
	PartitionEntry.LBA_Start = lba_start;
	PartitionEntry.SecCount = sec_count;
	PartitionEntry.Bootable = bootable;
	PartitionEntry.PartitionType = part_type;
	PartitionEntry.PartitionNum = part_num;
	PartitionList.push_back(PartitionEntry);
	MEM2_free(buffer);
}
int PartitionHandle::FindPartitions()
{
	MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD *) malloc(MAX_SECTOR_SIZE);
	if(!mbr)
		return -1;

	// Read the first sector on the device
	if (!interface->readSectors(0, 1, mbr)) {
		free(mbr);
		return -1;
	}

	// If this is the devices master boot record
	if (mbr->signature != MBR_SIGNATURE) {
		free(mbr);
		return -1;
	}

	for (int i = 0; i < 4; i++)
	{
		PARTITION_RECORD * partition = (PARTITION_RECORD *) &mbr->partitions[i];

		if(partition->type == PARTITION_TYPE_GPT)
		{
			int ret = CheckGPT(i);
			if(ret == 0)
				break;
		}

		if(partition->type == PARTITION_TYPE_DOS33_EXTENDED || partition->type == PARTITION_TYPE_WIN95_EXTENDED)
		{
			CheckEBR(i, le32(partition->lba_start));
			continue;
		}

		if(le32(partition->block_count) > 0)
		{
			AddPartition(PartFromType(partition->type), le32(partition->lba_start),
						 le32(partition->block_count), (partition->status == PARTITION_BOOTABLE),
						 partition->type, i);
		}
	}

	free(mbr);

	return 0;
}
s8 PartitionHandle::FindPartitions()
{
	MASTER_BOOT_RECORD *mbr = (MASTER_BOOT_RECORD*)MEM2_alloc(MAX_BYTES_PER_SECTOR);
	if(mbr == NULL)
		return -1;

	// Read the first sector on the device
	if(!interface->readSectors(0, 1, mbr))
	{
		MEM2_free(mbr);
		return -1;
	}

	// If this is the devices master boot record
	if(mbr->signature != MBR_SIGNATURE && mbr->signature != MBR_SIGNATURE_MOD)
	{
		MEM2_free(mbr);
		return -1;
	}

	for(u8 i = 0; i < 4; i++)
	{
		PARTITION_RECORD *partition = (PARTITION_RECORD *)&mbr->partitions[i];

		if(partition->type == PARTITION_TYPE_GPT)
		{
			s8 ret = CheckGPT(i);
			if(ret == 0) // if it's a GPT we don't need to go on looking through the mbr anymore
				return ret;
		}
		if(partition->type == PARTITION_TYPE_DOS33_EXTENDED || partition->type == PARTITION_TYPE_WIN95_EXTENDED)
		{
			CheckEBR(i, le32(partition->lba_start));
			continue;
		}
		if(le32(partition->block_count) > 0 && !IsExisting(le32(partition->lba_start)))
		{
			AddPartition(PartFromType(partition->type), le32(partition->lba_start),
					le32(partition->block_count), (partition->status == PARTITION_BOOTABLE), partition->type, i);
		}
	}
	MEM2_free(mbr);
	return 0;
}
void PartitionHandle::AddPartition(const char * name, u64 lba_start, u64 sec_count, bool bootable, u8 part_type, u8 part_num, u32 EBR_Sector)
{
	if(IsExisting(lba_start))
		return;

	u8 *buffer = new u8[MAX_SECTOR_SIZE];

	if (!interface->readSectors(lba_start, 1, buffer)) {
		delete [] buffer;
		return;
	}

	//! Partition typ can be missleading the correct partition format. Stupid lazy ass Partition Editors.
	if((memcmp(buffer + 0x36, "FAT", 3) == 0 || memcmp(buffer + 0x52, "FAT", 3) == 0) &&
		strncmp(PartFromType(part_type), "FAT", 3) != 0)
	{
		name = "FAT32";
		part_type = 0x0c;
	}
	if (memcmp(buffer + 0x03, "NTFS", 4) == 0)
	{
		name = "NTFS";
		part_type = 0x07;
	}

	int part = PartitionList.size();
	PartitionList.resize(part+1);

	PartitionList[part].FSName = name;
	PartitionList[part].LBA_Start = lba_start;
	PartitionList[part].SecCount = sec_count;
	PartitionList[part].Bootable = bootable;
	PartitionList[part].PartitionType = part_type;
	PartitionList[part].PartitionNum = part_num;
	PartitionList[part].EBR_Sector = EBR_Sector;
	delete [] buffer;
}