Example #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;
}
Example #2
0
// _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;
}
Example #3
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;
}
Example #4
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;
}