From 0e9f724cf848a82b76a65ea6c5144d197c554495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 2 Oct 2006 22:49:32 +0000 Subject: [PATCH] * When run as part of the boot loader, it will now adjust the size of partitions to fit into the session - this should help bug #238 to disappear. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18988 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../intel/PartitionMap.cpp | 144 ++++++++++-------- .../partitioning_systems/intel/PartitionMap.h | 15 +- .../intel/PartitionMapParser.cpp | 68 +++++---- .../intel/PartitionMapParser.h | 47 +++--- 4 files changed, 156 insertions(+), 118 deletions(-) diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index 71019f5f12..0fd0cbb5d8 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -84,9 +84,9 @@ static const struct partition_type kPartitionTypes[] = { { 0, NULL } }; + // partition_type_string -static -const char * +static const char * partition_type_string(uint8 type) { int32 i; @@ -111,7 +111,58 @@ get_partition_type_string(uint8 type, char *buffer) } -// Partition +static int +cmp_partition_offset(const void *p1, const void *p2) +{ + const Partition *partition1 = *(const Partition**)p1; + const Partition *partition2 = *(const Partition**)p2; + if (partition1->Offset() < partition2->Offset()) + return -1; + else if (partition1->Offset() > partition2->Offset()) + return 1; + return 0; +} + + +static int +cmp_offset(const void *o1, const void *o2) +{ + off_t offset1 = *static_cast(o1); + off_t offset2 = *static_cast(o2); + if (offset1 < offset2) + return -1; + else if (offset1 > offset2) + return 1; + return 0; +} + + +static bool +is_inside_partitions(off_t location, const Partition **partitions, int32 count) +{ + bool result = false; + if (count > 0) { + // binary search + int32 lower = 0; + int32 upper = count - 1; + while (lower < upper) { + int32 mid = (lower + upper) / 2; + const Partition *midPartition = partitions[mid]; + if (location >= midPartition->Offset() + midPartition->Size()) + lower = mid + 1; + else + upper = mid; + } + const Partition *partition = partitions[lower]; + result = (location >= partition->Offset() && + location < partition->Offset() + partition->Size()); + } + return result; +} + + +// #pragma mark - Partition + // constructor Partition::Partition() @@ -161,21 +212,35 @@ Partition::Unset() fActive = false; } -// CheckLocation + +#ifdef _BOOT_MODE +void +Partition::AdjustSize(off_t sessionSize) +{ + // To work around buggy (or older) BIOS, we shrink the partition size to + // always fit into its session - this should improve detection of boot + // partitions (see bug #238 for more information) + if (sessionSize > fOffset + fSize) + fSize = sessionSize - fOffset; +} +#endif + + bool Partition::CheckLocation(off_t sessionSize, int32 blockSize) const { // offsets and size must be block aligned, PTS and partition must lie // within the session - return (fPTSOffset % blockSize == 0 - && fOffset % blockSize == 0 - && fSize % blockSize == 0 - && fPTSOffset >= 0 && fPTSOffset < sessionSize - && fOffset >= 0 && fOffset + fSize <= sessionSize); + return fPTSOffset % blockSize == 0 + && fOffset % blockSize == 0 + && fSize % blockSize == 0 + && fPTSOffset >= 0 && fPTSOffset < sessionSize + && fOffset >= 0 && fOffset + fSize <= sessionSize; } -// PrimaryPartition +// #pragma mark - PrimaryPartition + // constructor PrimaryPartition::PrimaryPartition() @@ -249,7 +314,8 @@ PrimaryPartition::AddLogicalPartition(LogicalPartition *partition) } -// LogicalPartition +// #pragma mark - LogicalPartition + // constructor LogicalPartition::LogicalPartition() @@ -295,7 +361,8 @@ LogicalPartition::Unset() } -// PartitionMap +// #pragma mark - PartitionMap + // constructor PartitionMap::PartitionMap() @@ -387,59 +454,6 @@ PartitionMap::PartitionAt(int32 index) const return const_cast(this)->PartitionAt(index); } -// cmp_partition_offset -static -int -cmp_partition_offset(const void *p1, const void *p2) -{ - const Partition *partition1 = *(const Partition**)p1; - const Partition *partition2 = *(const Partition**)p2; - if (partition1->Offset() < partition2->Offset()) - return -1; - else if (partition1->Offset() > partition2->Offset()) - return 1; - return 0; -} - -// cmp_offset -static -int -cmp_offset(const void *o1, const void *o2) -{ - off_t offset1 = *static_cast(o1); - off_t offset2 = *static_cast(o2); - if (offset1 < offset2) - return -1; - else if (offset1 > offset2) - return 1; - return 0; -} - -// is_inside_partitions -static -bool -is_inside_partitions(off_t location, const Partition **partitions, int32 count) -{ - bool result = false; - if (count > 0) { - // binary search - int32 lower = 0; - int32 upper = count - 1; - while (lower < upper) { - int32 mid = (lower + upper) / 2; - const Partition *midPartition = partitions[mid]; - if (location >= midPartition->Offset() + midPartition->Size()) - lower = mid + 1; - else - upper = mid; - } - const Partition *partition = partitions[lower]; - result = (location >= partition->Offset() && - location < partition->Offset() + partition->Size()); - } - return result; -} - // Check bool PartitionMap::Check(off_t sessionSize, int32 blockSize) const diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h index aff888ac97..6d930a653c 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h @@ -1,7 +1,11 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the OpenBeOS license. -//--------------------------------------------------------------------- +/* + * Copyright 2003-2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold, bonefish@cs.tu-berlin.de + */ + /*! \file PartitionMap.h \brief Definitions for "intel" style partitions and interface definitions @@ -104,6 +108,9 @@ public: void SetActive(bool active) { fActive = active; } bool CheckLocation(off_t sessionSize, int32 blockSize) const; +#ifdef _BOOT_MODE + void AdjustSize(off_t sessionSize); +#endif private: off_t fPTSOffset; diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp index 1c94936bc1..07d9f89519 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp @@ -88,45 +88,50 @@ PartitionMapParser::Parse(const uint8 *block, PartitionMap *map) status_t PartitionMapParser::_ParsePrimary(const partition_table_sector *pts) { - status_t error = (pts ? B_OK : B_BAD_VALUE); + if (pts == NULL) + return B_BAD_VALUE; + // check the signature - if (error == B_OK && pts->signature != kPartitionTableSectorSignature) { + if (pts->signature != kPartitionTableSectorSignature) { TRACE(("intel: _ParsePrimary(): invalid PTS signature\n")); - error = B_BAD_DATA; + return B_BAD_DATA; } + // examine the table - if (error == B_OK) { - for (int32 i = 0; i < 4; i++) { - const partition_descriptor *descriptor = &pts->table[i]; - PrimaryPartition *partition = fMap->PrimaryPartitionAt(i); - partition->SetTo(descriptor, 0, fBlockSize); - // ignore, if location is bad - if (!partition->CheckLocation(fSessionSize, fBlockSize)) { - TRACE(("intel: _ParsePrimary(): partition %ld: bad location, " - "ignoring\n", i)); - partition->Unset(); - } + for (int32 i = 0; i < 4; i++) { + const partition_descriptor *descriptor = &pts->table[i]; + PrimaryPartition *partition = fMap->PrimaryPartitionAt(i); + partition->SetTo(descriptor, 0, fBlockSize); + +#ifdef _BOOT_MODE + // work-around potential BIOS problems + partition->AdjustSize(fSessionSize); +#endif + // ignore, if location is bad + if (!partition->CheckLocation(fSessionSize, fBlockSize)) { + TRACE(("intel: _ParsePrimary(): partition %ld: bad location, " + "ignoring\n", i)); + partition->Unset(); } } + // allocate a PTS buffer - if (error == B_OK) { - fPTS = new(nothrow) partition_table_sector; - if (!fPTS) - error = B_NO_MEMORY; - } + fPTS = new(nothrow) partition_table_sector; + if (fPTS == NULL) + return B_NO_MEMORY; + // parse extended partitions - if (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()); - } + 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 - if (fPTS) { - delete fPTS; - fPTS = NULL; - } + delete fPTS; + fPTS = NULL; + return error; } @@ -193,6 +198,11 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset) "non-extended partition allowed\n")); } } +#ifdef _BOOT_MODE + // work-around potential BIOS problems + if (partition) + partition->AdjustSize(fSessionSize); +#endif // check the partition's location if (partition && !partition->CheckLocation(fSessionSize, fBlockSize)) { diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h index 3d74637a6d..da03b0d7e0 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h @@ -1,38 +1,45 @@ -// PartitionMapParser.h - +/* + * Copyright 2003-2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold, bonefish@cs.tu-berlin.de + */ #ifndef PARTITION_MAP_PARSER_H #define PARTITION_MAP_PARSER_H + #include + class Partition; class PartitionMap; class PrimaryPartition; struct partition_table_sector; class PartitionMapParser { -public: - PartitionMapParser(int deviceFD, off_t sessionOffset, off_t sessionSize, - int32 blockSize); - ~PartitionMapParser(); + public: + PartitionMapParser(int deviceFD, off_t sessionOffset, off_t sessionSize, + int32 blockSize); + ~PartitionMapParser(); - status_t Parse(const uint8 *block, PartitionMap *map); + status_t Parse(const uint8 *block, PartitionMap *map); - int32 CountPartitions() const; - const Partition *PartitionAt(int32 index) const; + int32 CountPartitions() const; + const Partition *PartitionAt(int32 index) const; -private: - status_t _ParsePrimary(const partition_table_sector *pts); - status_t _ParseExtended(PrimaryPartition *primary, off_t offset); - status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL); + private: + status_t _ParsePrimary(const partition_table_sector *pts); + status_t _ParseExtended(PrimaryPartition *primary, off_t offset); + status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL); -private: - int fDeviceFD; - off_t fSessionOffset; - off_t fSessionSize; - int32 fBlockSize; - partition_table_sector *fPTS; // while parsing - PartitionMap *fMap; // + private: + int fDeviceFD; + off_t fSessionOffset; + off_t fSessionSize; + int32 fBlockSize; + partition_table_sector *fPTS; // while parsing + PartitionMap *fMap; }; #endif // PARTITION_MAP_PARSER_H