Beispiel #1
0
status_t
Header::Write(int fd)
{
	// Try to write the protective MBR
	PartitionMap partitionMap;
	PrimaryPartition *partition = NULL;
	uint32 index = 0;
	while ((partition = partitionMap.PrimaryPartitionAt(index)) != NULL) {
		if (index == 0) {
			uint64 deviceSize = fHeader.AlternateBlock() * fBlockSize;
			partition->SetTo(fBlockSize, deviceSize, 0xEE, false, fBlockSize);
		} else
			partition->Unset();
		++index;
	}
	PartitionMapWriter writer(fd, fBlockSize);
	writer.WriteMBR(&partitionMap, true);
		// We also write the bootcode, so we can boot GPT disks from BIOS

	status_t status = _Write(fd, fHeader.EntriesBlock() * fBlockSize, fEntries,
		_EntryArraySize());
	if (status != B_OK)
		return status;

	// First write the header, so that we have at least one completely correct
	// data set
	status = _WriteHeader(fd);


	// Write backup entries
	status_t backupStatus = _Write(fd,
		fBackupHeader.EntriesBlock() * fBlockSize, fEntries, _EntryArraySize());

	return status == B_OK ? backupStatus : status;
}
void
LogicalPartition::GetPartitionDescriptor(partition_descriptor* descriptor,
	bool inner) const
{
	PrimaryPartition* primary = GetPrimaryPartition();
	if (inner) {
		descriptor->start = (PartitionTableOffset() - primary->Offset())
			/ BlockSize();
		descriptor->type = primary->Type();
	} else {
		descriptor->start = (Offset() - PartitionTableOffset()) / BlockSize();
		descriptor->type = Type();
	}

	descriptor->size = Size() / BlockSize();
	descriptor->active = 0x00;
	descriptor->begin.Unset();
	descriptor->end.Unset();
}
// _ParsePrimary
status_t
PartitionMapParser::_ParsePrimary(const partition_table* table,
	bool& hadToReFitSize)
{
	if (table == NULL)
		return B_BAD_VALUE;

	// check the signature
	if (table->signature != kPartitionTableSectorSignature) {
		TRACE(("intel: _ParsePrimary(): invalid PartitionTable signature: %lx\n",
			(uint32)table->signature));
		return B_BAD_DATA;
	}

	hadToReFitSize = false;

	// examine the table
	for (int32 i = 0; i < 4; i++) {
		const partition_descriptor* descriptor = &table->table[i];
		PrimaryPartition* partition = fMap->PrimaryPartitionAt(i);
		partition->SetTo(descriptor, 0, fBlockSize);

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

		// ignore, if location is bad
		if (!partition->CheckLocation(fSessionSize)) {
			TRACE(("intel: _ParsePrimary(): partition %ld: bad location, "
				"ignoring\n", i));
			partition->Unset();
		}
	}

	// allocate a partition_table buffer
	fPartitionTable = new(nothrow) partition_table;
	if (fPartitionTable == NULL)
		return B_NO_MEMORY;

	// parse extended partitions
	status_t error = B_OK;
	for (int32 i = 0; error == B_OK && i < 4; i++) {
		PrimaryPartition* primary = fMap->PrimaryPartitionAt(i);
		if (primary->IsExtended())
			error = _ParseExtended(primary, primary->Offset());
	}

	// cleanup
	delete fPartitionTable;
	fPartitionTable = NULL;

	return error;
}
Beispiel #4
0
status_t
PartitionMapHandle::Init()
{
    // initialize the partition map from the mutable partition

    BMutablePartition* partition = Partition();

    int32 count = partition->CountChildren();
    if (count > 4)
        return B_BAD_VALUE;

    int32 extendedCount = 0;

    for (int32 i = 0; i < count; i++) {
        BMutablePartition* child = partition->ChildAt(i);
        PartitionType type;
        if (!type.SetType(child->Type()))
            return B_BAD_VALUE;

        // only one extended partition is allowed
        if (type.IsExtended()) {
            if (++extendedCount > 1)
                return B_BAD_VALUE;
        }

        // TODO: Get these from the parameters.
        int32 index = i;
        bool active = false;

        PrimaryPartition* primary = fPartitionMap.PrimaryPartitionAt(index);
        primary->SetTo(child->Offset(), child->Size(), type.Type(), active,
                       partition->BlockSize());

        child->SetChildCookie(primary);
    }

    // The extended partition (if any) is initialized by
    // ExtendedPartitionHandle::Init().

    return B_OK;
}
Beispiel #5
0
status_t
PartitionMapHandle::GetPartitioningInfo(BPartitioningInfo* info)
{
    // init to the full size (minus the first sector)
    off_t size = Partition()->ContentSize();
    status_t error = info->SetTo(Partition()->BlockSize(),
                                 size - Partition()->BlockSize());
    if (error != B_OK)
        return error;

    // exclude the space of the existing partitions
    for (int32 i = 0; i < 4; i++) {
        PrimaryPartition* primary = fPartitionMap.PrimaryPartitionAt(i);
        if (!primary->IsEmpty()) {
            error = info->ExcludeOccupiedSpace(primary->Offset(),
                                               primary->Size());
            if (error != B_OK)
                return error;
        }
    }

    return B_OK;
}
status_t
PrimaryPartition::Assign(const PrimaryPartition& other)
{
	partition_descriptor descriptor;
	other.GetPartitionDescriptor(&descriptor);
	SetTo(&descriptor, 0, other.BlockSize());

	const LogicalPartition* otherLogical = other.fHead;
	while (otherLogical) {
		off_t tableOffset = otherLogical->PartitionTableOffset();
		otherLogical->GetPartitionDescriptor(&descriptor);

		LogicalPartition* logical = new(nothrow) LogicalPartition(
			&descriptor, tableOffset, this);
		if (!logical)
			return B_NO_MEMORY;

		AddLogicalPartition(logical);

		otherLogical = otherLogical->Next();
	}

	return B_OK;
}
Beispiel #7
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;
}
Beispiel #8
0
// pm_scan_partition
static status_t
pm_scan_partition(int fd, partition_data* partition, void* cookie)
{
	// check parameters
	if (fd < 0 || !partition || !cookie)
		return B_ERROR;

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

	PartitionMapCookie* map = (PartitionMapCookie*)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 = map;
	// children
	status_t error = B_OK;
	int32 index = 0;
	for (int32 i = 0; i < 4; i++) {
		PrimaryPartition* primary = map->PrimaryPartitionAt(i);
		if (!primary->IsEmpty()) {
			partition_data* child = create_child_partition(partition->id,
				index, partition->offset + primary->Offset(), primary->Size(),
				-1);
			index++;
			if (!child) {
				// something went wrong
				error = B_ERROR;
				break;
			}

			child->block_size = partition->block_size;

			// (no name)
			char type[B_FILE_NAME_LENGTH];
			primary->GetTypeString(type);
			child->type = strdup(type);
			// parameters
			char buffer[128];
			sprintf(buffer, "type = %u ; active = %d", primary->Type(),
				primary->Active());
			child->parameters = strdup(buffer);
			child->cookie = primary;
			// check for allocation problems
			if (!child->type || !child->parameters) {
				error = B_NO_MEMORY;
				break;
			}
		}
	}

	// keep map on success or cleanup on error
	if (error == B_OK) {
		atomic_add(&map->ref_count, 1);
	} else {
		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;
}
Beispiel #9
0
status_t
PartitionMapHandle::CreateChild(off_t offset, off_t size,
                                const char* typeString, const char* name, const char* parameters,
                                BMutablePartition** _child)
{
    // check type
    PartitionType type;
    if (!type.SetType(typeString) || type.IsEmpty())
        return B_BAD_VALUE;
    if (type.IsExtended() && fPartitionMap.ExtendedPartitionIndex() >= 0)
        return B_BAD_VALUE;

    // check name
    if (name && *name != '\0')
        return B_BAD_VALUE;

    // check parameters
    void* handle = parse_driver_settings_string(parameters);
    if (handle == NULL)
        return B_ERROR;

    bool active = get_driver_boolean_parameter(handle, "active", false, true);
    delete_driver_settings(handle);

    // get a spare primary partition
    PrimaryPartition* primary = NULL;
    for (int32 i = 0; i < 4; i++) {
        if (fPartitionMap.PrimaryPartitionAt(i)->IsEmpty()) {
            primary = fPartitionMap.PrimaryPartitionAt(i);
            break;
        }
    }
    if (!primary)
        return B_BAD_VALUE;

    // offset properly aligned?
    if (offset != sector_align(offset, Partition()->BlockSize())
            || size != sector_align(size, Partition()->BlockSize()))
        return B_BAD_VALUE;

    // check the free space situation
    BPartitioningInfo info;
    status_t error = GetPartitioningInfo(&info);
    if (error != B_OK)
        return error;

    bool foundSpace = false;
    off_t end = offset + size;
    int32 spacesCount = info.CountPartitionableSpaces();
    for (int32 i = 0; i < spacesCount; i++) {
        off_t spaceOffset, spaceSize;
        info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
        off_t spaceEnd = spaceOffset + spaceSize;

        if (offset >= spaceOffset && end <= spaceEnd) {
            foundSpace = true;
            break;
        }
    }

    if (!foundSpace)
        return B_BAD_VALUE;

    // create the child
    // (Note: the primary partition index is indeed the child index, since
    // we picked the first empty primary partition.)
    BMutablePartition* partition = Partition();
    BMutablePartition* child;
    error = partition->CreateChild(primary->Index(), typeString, name,
                                   parameters, &child);
    if (error != B_OK)
        return error;

    // init the child
    child->SetOffset(offset);
    child->SetSize(size);
    child->SetBlockSize(partition->BlockSize());
    //child->SetFlags(0);
    child->SetChildCookie(primary);

    // init the primary partition
    primary->SetTo(offset, size, type.Type(), active, partition->BlockSize());

    *_child = child;
    return B_OK;
}