status_t ExtendedPartitionHandle::GetPartitioningInfo(BPartitioningInfo* info) { // init to the full size (minus the first PTS_OFFSET) BMutablePartition* partition = Partition(); off_t offset = partition->Offset() + PTS_OFFSET; off_t size = partition->Size() - PTS_OFFSET; status_t error = info->SetTo(offset, size); if (error != B_OK) return error; // exclude the space of the existing logical partitions int32 count = partition->CountChildren(); for (int32 i = 0; i < count; i++) { BMutablePartition* child = partition->ChildAt(i); error = info->ExcludeOccupiedSpace(child->Offset(), child->Size() + PTS_OFFSET + Partition()->BlockSize()); if (error != B_OK) return error; LogicalPartition* logical = (LogicalPartition*)child->ChildCookie(); if (logical == NULL) return B_BAD_VALUE; error = info->ExcludeOccupiedSpace( logical->PartitionTableOffset(), PTS_OFFSET + Partition()->BlockSize()); if (error != B_OK) return error; } return B_OK; }
LogicalPartition* PrimaryPartition::LogicalPartitionAt(int32 index) const { LogicalPartition* partition = NULL; if (index >= 0 && index < fLogicalPartitionCount) { for (partition = fHead; index > 0; index--) partition = partition->Next(); } return partition; }
status_t ExtendedPartitionHandle::Init() { // initialize the extended partition from the mutable partition BMutablePartition* partition = Partition(); // our parent has already set the child cookie to the primary partition. fPrimaryPartition = (PrimaryPartition*)partition->ChildCookie(); if (!fPrimaryPartition) return B_BAD_VALUE; if (!fPrimaryPartition->IsExtended()) return B_BAD_VALUE; // init the child partitions int32 count = partition->CountChildren(); for (int32 i = 0; i < count; i++) { BMutablePartition* child = partition->ChildAt(i); PartitionType type; if (!type.SetType(child->Type())) return B_BAD_VALUE; void* handle = parse_driver_settings_string(child->Parameters()); if (handle == NULL) return B_ERROR; bool active = get_driver_boolean_parameter( handle, "active", false, true); off_t ptsOffset = 0; const char* buffer = get_driver_parameter(handle, "partition_table_offset", NULL, NULL); if (buffer != NULL) ptsOffset = strtoull(buffer, NULL, 10); else { delete_driver_settings(handle); return B_BAD_VALUE; } delete_driver_settings(handle); LogicalPartition* logical = new(nothrow) LogicalPartition; if (!logical) return B_NO_MEMORY; logical->SetTo(child->Offset(), child->Size(), type.Type(), active, ptsOffset, fPrimaryPartition); child->SetChildCookie(logical); } return B_OK; }
status_t PartitionMapWriter::WriteExtendedHead(const LogicalPartition* logical, const PrimaryPartition* primary, bool clearCode) { if (primary == NULL) return B_BAD_VALUE; partition_table partitionTable; if (clearCode) { partitionTable.clear_code_area(); } else { status_t error = _ReadBlock(primary->Offset(), partitionTable); if (error != B_OK) return error; } partitionTable.signature = kPartitionTableSectorSignature; partition_descriptor* descriptor; if (logical == NULL) { for (int32 i = 0; i < 4; i++) { descriptor = &partitionTable.table[i]; memset(descriptor, 0, sizeof(partition_descriptor)); } } else { LogicalPartition partition; partition.SetPartitionTableOffset(primary->Offset()); partition.SetBlockSize(logical->BlockSize()); partition.SetOffset(logical->Offset()); partition.SetSize(logical->Size()); partition.SetType(logical->Type()); // set the logicals partition table to the correct location descriptor = &partitionTable.table[0]; partition.GetPartitionDescriptor(descriptor); descriptor = &partitionTable.table[1]; LogicalPartition* next = logical->Next(); if (next != NULL) next->GetPartitionDescriptor(descriptor, true); else memset(descriptor, 0, sizeof(partition_descriptor)); // last two descriptors are empty for (int32 i = 2; i < 4; i++) { descriptor = &partitionTable.table[i]; memset(descriptor, 0, sizeof(partition_descriptor)); } } status_t error = _WriteBlock(primary->Offset(), partitionTable); if (error != B_OK) return error; return B_OK; }
void PrimaryPartition::RemoveLogicalPartition(LogicalPartition* partition) { if (!partition || partition->GetPrimaryPartition() != this) return; LogicalPartition* prev = partition->Previous(); LogicalPartition* next = partition->Next(); if (prev) prev->SetNext(next); else fHead = next; if (next) next->SetPrevious(prev); else fTail = prev; fLogicalPartitionCount--; partition->SetNext(NULL); partition->SetPrevious(NULL); partition->SetPrimaryPartition(NULL); }
// _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; }
// 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; }