diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index f31dc4febf..3f2d9f3d50 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -508,17 +508,19 @@ PrimaryPartition::LogicalPartitionAt(int32 index) const void PrimaryPartition::AddLogicalPartition(LogicalPartition *partition) { - if (partition) { - partition->SetPrimaryPartition(this); - partition->SetPrevious(fTail); - if (fTail) { - fTail->SetNext(partition); - fTail = partition; - } else - fHead = fTail = partition; - partition->SetNext(NULL); - fLogicalPartitionCount++; - } + if (!partition) + return; + + partition->SetPrimaryPartition(this); + partition->SetPrevious(fTail); + if (fTail) { + fTail->SetNext(partition); + fTail = partition; + } else + fHead = fTail = partition; + partition->SetNext(NULL); + + fLogicalPartitionCount++; } // RemoveLogicalPartition @@ -538,6 +540,7 @@ PrimaryPartition::RemoveLogicalPartition(LogicalPartition *partition) next->SetPrevious(prev); else fTail = prev; + fLogicalPartitionCount--; partition->SetNext(NULL); diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp index 7441932540..0caf2375d3 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp @@ -168,7 +168,13 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset) // Examine the table, there is exactly one extended and one // non-extended logical partition. All four table entries are - // examined though. + // examined though. If there is no inner extended partition, + // the end of the linked list is reached. + // The first PTS 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 PTS in the linked list + // is the start sector of the inner extended partition described in + // this PTS. LogicalPartition extended; LogicalPartition nonExtended; for (int32 i = 0; error == B_OK && i < 4; i++) { @@ -224,7 +230,7 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset) error = B_NO_MEMORY; } - // prepare to parse next extended partition + // prepare to parse next extended/non-extended partition pair if (error == B_OK && !extended.IsEmpty()) offset = extended.Offset(); else diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp index db69c1d332..962c5391c9 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp @@ -226,23 +226,38 @@ PartitionMapWriter::_WriteExtended(partition_table_sector *pts, return B_BAD_DATA; } + // NOTE: The OS/2 boot manager needs the first entry to describe the + // data partition, while the second entry should describe the "inner + // extended" partition. + // write the table partition_descriptor* descriptor = &(pts->table[0]); partition->GetPartitionDescriptor(descriptor, partition->PTSOffset()); // location is relative to this partitions PTS offset - // setting offset and size of the next partition in the linked list + // Set offset and size of the next partition in the linked list. + // This is done via a so called "inner extended" partition which is + // only used to point to the next PTS location (start sector of the + // inner extended partition). descriptor = &(pts->table[1]); LogicalPartition extended; if (next) { extended.SetPTSOffset(partition->PTSOffset()); extended.SetOffset(next->PTSOffset()); - extended.SetSize(next->Size() + next->Offset() - next->PTSOffset()); - // TODO: The size calculation looks suspicious. - // Isn't next->Offset() relative to primary extended patition while - // next->PTSOffset() is not? + + // Strictly speaking, the size is not relevant and just needs to + // be non-zero. But some operating systems check the size of + // inner extended partitions and it needs to include the next data + // partition. Therefor the size is the size of the next data partition + // plus the offset between the next PTS and the data partition start + // offset. This assumes of course that the start offset is behind + // the PTS offset, which is actually not dictated by a minimal + // specification. + extended.SetSize(next->Size() + (next->Offset() - next->PTSOffset())); + + // Use the same extended partition type as the primary extended + // partition. extended.SetType(partition->GetPrimaryPartition()->Type()); - // TODO: Weird. extended.GetPartitionDescriptor(descriptor, 0);