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