Example #1
0
// _ParseExtended
status_t
PartitionMapParser::_ParseExtended(PrimaryPartition* primary, off_t offset)
{
	status_t error = B_OK;
	int32 partitionCount = 0;
	while (error == B_OK) {
		// check for cycles
		if (++partitionCount > kMaxLogicalPartitionCount) {
			TRACE(("intel: _ParseExtended(): Maximal number of logical "
				   "partitions for extended partition reached. Cycle?\n"));
			error = B_BAD_DATA;
		}

		// read the partition table
		if (error == B_OK)
			error = _ReadPartitionTable(offset);

		// check the signature
		if (error == B_OK
			&& fPartitionTable->signature != kPartitionTableSectorSignature) {
			TRACE(("intel: _ParseExtended(): invalid partition table signature: "
				"%lx\n", (uint32)fPartitionTable->signature));
			error = B_BAD_DATA;
		}

		// ignore the partition table, if any error occured till now
		if (error != B_OK) {
			TRACE(("intel: _ParseExtended(): ignoring this partition table\n"));
			error = B_OK;
			break;
		}

		// Examine the table, there is exactly one extended and one
		// non-extended logical partition. All four table entries are
		// examined though. If there is no inner extended partition,
		// the end of the linked list is reached.
		// The first partition table describing both an "inner extended" parition
		// and a "data" partition (non extended and not empty) is the start
		// sector of the primary extended partition. The next partition table in
		// the linked list is the start sector of the inner extended partition
		// described in this partition table.
		LogicalPartition extended;
		LogicalPartition nonExtended;
		for (int32 i = 0; error == B_OK && i < 4; i++) {
			const partition_descriptor* descriptor = &fPartitionTable->table[i];
			if (descriptor->is_empty())
				continue;

			LogicalPartition* partition = NULL;
			if (descriptor->is_extended()) {
				if (extended.IsEmpty()) {
					extended.SetTo(descriptor, offset, primary);
					partition = &extended;
				} else {
					// only one extended partition allowed
					error = B_BAD_DATA;
					TRACE(("intel: _ParseExtended(): "
						   "only one extended partition allowed\n"));
				}
			} else {
				if (nonExtended.IsEmpty()) {
					nonExtended.SetTo(descriptor, offset, primary);
					partition = &nonExtended;
				} else {
					// only one non-extended partition allowed
					error = B_BAD_DATA;
					TRACE(("intel: _ParseExtended(): only one "
						   "non-extended partition allowed\n"));
				}
			}
			if (partition == NULL)
				break;

			// work-around potential BIOS/OS problems
			partition->FitSizeToSession(fSessionSize);

			// check the partition's location
			if (!partition->CheckLocation(fSessionSize)) {
				error = B_BAD_DATA;
				TRACE(("intel: _ParseExtended(): Invalid partition "
					"location: pts: %lld, offset: %lld, size: %lld\n",
					partition->PartitionTableOffset(), partition->Offset(),
					partition->Size()));
			}
		}

		// add non-extended partition to list
		if (error == B_OK && !nonExtended.IsEmpty()) {
			LogicalPartition* partition
				= new(nothrow) LogicalPartition(nonExtended);
			if (partition)
				primary->AddLogicalPartition(partition);
			else
				error = B_NO_MEMORY;
		}

		// prepare to parse next extended/non-extended partition pair
		if (error == B_OK && !extended.IsEmpty())
			offset = extended.Offset();
		else
			break;
	}

	return error;
}
Example #2
0
// ep_scan_partition
static status_t
ep_scan_partition(int fd, partition_data* partition, void* cookie)
{
	// check parameters
	if (fd < 0 || !partition || !partition->cookie)
		return B_ERROR;

	TRACE(("intel: ep_scan_partition(%d, %lld, %lld, %ld)\n", fd,
		partition->offset, partition->size, partition->block_size));

	partition_data* parent = get_parent_partition(partition->id);
	if (!parent)
		return B_ERROR;

	PrimaryPartition* primary = (PrimaryPartition*)partition->cookie;
	// fill in the partition_data structure
	partition->status = B_PARTITION_VALID;
	partition->flags |= B_PARTITION_PARTITIONING_SYSTEM;
	partition->content_size = partition->size;
	// (no content_name and content_parameters)
	// (content_type is set by the system)

	partition->content_cookie = primary;
	// children
	status_t error = B_OK;
	int32 index = 0;
	for (int32 i = 0; i < primary->CountLogicalPartitions(); i++) {
		LogicalPartition* logical = primary->LogicalPartitionAt(i);
		partition_data* child = create_child_partition(partition->id, index,
			parent->offset + logical->Offset(), logical->Size(), -1);
		index++;
		if (!child) {
			// something went wrong
			TRACE(("intel: ep_scan_partition(): failed to create child "
				"partition\n"));
			error = B_ERROR;
			break;
		}
		child->block_size = partition->block_size;

		// (no name)
		char type[B_FILE_NAME_LENGTH];
		logical->GetTypeString(type);
		child->type = strdup(type);

		// parameters
		char buffer[128];
		sprintf(buffer, "active %s ;\npartition_table_offset %lld ;\n",
			logical->Active() ? "true" : "false",
			logical->PartitionTableOffset());
		child->parameters = strdup(buffer);
		child->cookie = logical;
		// check for allocation problems
		if (!child->type || !child->parameters) {
			TRACE(("intel: ep_scan_partition(): failed to allocation type "
				"or parameters\n"));
			error = B_NO_MEMORY;
			break;
		}
	}

	// cleanup on error
	if (error != B_OK) {
		partition->content_cookie = NULL;
		for (int32 i = 0; i < partition->child_count; i++) {
			if (partition_data* child = get_child_partition(partition->id, i))
				child->cookie = NULL;
		}
	}
	return error;
}