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;
}