From e4c0070fe64f204140fdd96ffef71e0ce7d36ba6 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 28 Feb 2010 18:10:29 +0000 Subject: [PATCH] Added a bit of logic to possibly fall back to a fixed 512 block MBR in case certain conditions indicate that we might deal with a fixed 512 bytes MBR on a non 512 byte block size medium. One condition is that at least one partition had to be shrunk to fit the available size (which usually happens with larger block sizes). We retry with a fixed 512 block size once and compare the result if it didn't improve the situation it is reverted again. This is mostly a preparation for the upcoming "anyboot" hybrid MBR/ISO images. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35664 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../intel/PartitionMap.cpp | 8 +++- .../partitioning_systems/intel/PartitionMap.h | 2 +- .../intel/PartitionMapParser.cpp | 40 ++++++++++++++++--- .../intel/PartitionMapParser.h | 3 +- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index a28b55f8c0..5ae0e5a14e 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -399,7 +399,7 @@ Partition::CheckLocation(off_t sessionSize) const } -void +bool Partition::FitSizeToSession(off_t sessionSize) { // To work around buggy (or older) BIOS, we shrink the partition size to @@ -408,8 +408,12 @@ Partition::FitSizeToSession(off_t sessionSize) // Also, the drive size is obviously reported differently sometimes; this // should let us read problematic drives - let the file system figure out // if something is wrong. - if (sessionSize < fOffset + fSize && sessionSize > fOffset) + if (sessionSize < fOffset + fSize && sessionSize > fOffset) { fSize = sessionSize - fOffset; + return true; + } + + return false; } diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h index c35fa2fa0f..647e10c6be 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h @@ -182,7 +182,7 @@ public: { fBlockSize = blockSize; } bool CheckLocation(off_t sessionSize) const; - void FitSizeToSession(off_t sessionSize); + bool FitSizeToSession(off_t sessionSize); private: off_t fPartitionTableOffset; diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp index a758d2a59b..e94b0201cb 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp @@ -67,18 +67,45 @@ PartitionMapParser::Parse(const uint8* block, PartitionMap* map) return B_BAD_VALUE; status_t error; + bool hadToReFitSize = false; fMap = map; fMap->Unset(); if (block) { const partition_table* table = (const partition_table*)block; - error = _ParsePrimary(table); + error = _ParsePrimary(table, hadToReFitSize); } else { partition_table table; error = _ReadPartitionTable(0, &table); - if (error == B_OK) - error = _ParsePrimary(&table); + if (error == B_OK) { + error = _ParsePrimary(&table, hadToReFitSize); + + if (fBlockSize != 512 && (hadToReFitSize + || !fMap->Check(fSessionSize))) { + // This might be a fixed 512 byte MBR on a non-512 medium. + // We do that for the anyboot images for example. so retry + // with a fixed 512 block size and see if we get better + // results + int32 previousPartitionCount = fMap->CountNonEmptyPartitions(); + uint32 previousBlockSize = fBlockSize; + TRACE(("intel: Parse(): trying with a fixed 512 block size\n")); + + fBlockSize = 512; + fMap->Unset(); + error = _ParsePrimary(&table, hadToReFitSize); + + if (fMap->CountNonEmptyPartitions() < previousPartitionCount + || error != B_OK || hadToReFitSize + || !fMap->Check(fSessionSize)) { + // That didn't improve anything, let's revert. + TRACE(("intel: Parse(): try failed, reverting\n")); + fBlockSize = previousBlockSize; + fMap->Unset(); + error = _ParsePrimary(&table, hadToReFitSize); + } + } + } } if (error == B_OK && !fMap->Check(fSessionSize)) @@ -92,7 +119,8 @@ PartitionMapParser::Parse(const uint8* block, PartitionMap* map) // _ParsePrimary status_t -PartitionMapParser::_ParsePrimary(const partition_table* table) +PartitionMapParser::_ParsePrimary(const partition_table* table, + bool& hadToReFitSize) { if (table == NULL) return B_BAD_VALUE; @@ -104,6 +132,8 @@ PartitionMapParser::_ParsePrimary(const partition_table* table) return B_BAD_DATA; } + hadToReFitSize = false; + // examine the table for (int32 i = 0; i < 4; i++) { const partition_descriptor* descriptor = &table->table[i]; @@ -111,7 +141,7 @@ PartitionMapParser::_ParsePrimary(const partition_table* table) partition->SetTo(descriptor, 0, fBlockSize); // work-around potential BIOS/OS problems - partition->FitSizeToSession(fSessionSize); + hadToReFitSize |= partition->FitSizeToSession(fSessionSize); // ignore, if location is bad if (!partition->CheckLocation(fSessionSize)) { diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h index 4ecf85b92f..7034bacdd9 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h @@ -38,7 +38,8 @@ public: const Partition* PartitionAt(int32 index) const; private: - status_t _ParsePrimary(const partition_table* table); + status_t _ParsePrimary(const partition_table* table, + bool& hadToReFitSize); status_t _ParseExtended(PrimaryPartition* primary, off_t offset); status_t _ReadPartitionTable(off_t offset,