From 569750e57f75b9e440f4cdbfd780ec49da53aace Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 2 Oct 2004 15:34:50 +0000 Subject: [PATCH] Refactored a bit -- pulled the partition map parser out. Userland add-on disabled for the time being, due to build problems. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9158 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/partitioning_systems/intel/Jamfile | 23 +- .../intel/PartitionMapParser.cpp | 217 +++++++++++++ .../intel/PartitionMapParser.h | 38 +++ .../partitioning_systems/intel/intel.cpp | 304 +++--------------- 4 files changed, 319 insertions(+), 263 deletions(-) create mode 100644 src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp create mode 100644 src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h diff --git a/src/add-ons/kernel/partitioning_systems/intel/Jamfile b/src/add-ons/kernel/partitioning_systems/intel/Jamfile index 0a9463f86a..9e2bea9ea9 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/Jamfile +++ b/src/add-ons/kernel/partitioning_systems/intel/Jamfile @@ -1,22 +1,25 @@ SubDir OBOS_TOP src add-ons kernel partitioning_systems intel ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; -UsePrivateHeaders [ FDirName kernel ] ; -UsePrivateHeaders [ FDirName storage ] ; +UsePrivateHeaders kernel ; +UsePrivateHeaders shared ; +UsePrivateHeaders storage ; KernelAddon intel : kernel partitioning_systems : intel.cpp PartitionMap.cpp + PartitionMapParser.cpp ; # Also build a userland version # ToDo: it's probably not a good idea to build them into the same directory -Addon intel : userland partitioning_systems : - intel.cpp - PartitionMap.cpp -; +#Addon intel : userland partitioning_systems : +# intel.cpp +# PartitionMap.cpp +# PartitionMapParser.cpp +#; -LinkSharedOSLibs intel : - libkernelland_emu.so - libdisk_device_manager.so -; +#LinkSharedOSLibs intel : +# libkernelland_emu.so +# libdisk_device_manager.so +#; diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp new file mode 100644 index 0000000000..71f2f4ad00 --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp @@ -0,0 +1,217 @@ +// PartitionMapParser.cpp + +#include +#include +#include + +#include + +#include "PartitionMap.h" +#include "PartitionMapParser.h" + +#define TRACE(x) ; +//#define TRACE(x) dprintf x + +// Maximal number of logical partitions per extended partition we allow. +static const int32 kMaxLogicalPartitionCount = 128; + +// constructor +PartitionMapParser::PartitionMapParser(int deviceFD, off_t sessionOffset, + off_t sessionSize, int32 blockSize) + : fDeviceFD(deviceFD), + fSessionOffset(sessionOffset), + fSessionSize(sessionSize), + fBlockSize(blockSize), + fPTS(NULL), + fMap(NULL) +{ +} + +// destructor +PartitionMapParser::~PartitionMapParser() +{ +} + +// Parse +status_t +PartitionMapParser::Parse(const uint8 *block, PartitionMap *map) +{ + status_t error = (map ? B_OK : B_BAD_VALUE); + if (error == B_OK) { + fMap = map; + fMap->Unset(); + if (block) { + const partition_table_sector *pts + = (const partition_table_sector*)block; + error = _ParsePrimary(pts); + } else { + partition_table_sector pts; + error = _ReadPTS(0, &pts); + if (error == B_OK) + error = _ParsePrimary(&pts); + } + if (error == B_OK && !fMap->Check(fSessionSize, fBlockSize)) + error = B_BAD_DATA; + fMap = NULL; + } + return error; +} + +// _ParsePrimary +status_t +PartitionMapParser::_ParsePrimary(const partition_table_sector *pts) +{ + status_t error = (pts ? B_OK : B_BAD_VALUE); + // check the signature + if (error == B_OK && pts->signature != kPartitionTableSectorSignature) { + TRACE(("intel: _ParsePrimary(): invalid PTS signature\n")); + error = 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); + // fail, if location is bad + if (!partition->CheckLocation(fSessionSize, fBlockSize)) { + error = B_BAD_DATA; + break; + } + } + } + // allocate a PTS buffer + if (error == B_OK) { + fPTS = new(nothrow) partition_table_sector; + if (!fPTS) + error = 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()); + } + } + // cleanup + if (fPTS) { + delete fPTS; + fPTS = NULL; + } + return error; +} + +// _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 PTS + if (error == B_OK) + error = _ReadPTS(offset); + // check the signature + if (error == B_OK + && fPTS->signature != kPartitionTableSectorSignature) { + TRACE(("intel: _ParseExtended(): invalid PTS signature\n")); + error = B_BAD_DATA; + } + // ignore the PTS, if any error occured till now + if (error != B_OK) { + TRACE(("intel: _ParseExtended(): ignoring this PTS\n")); + error = B_OK; + break; + } + // examine the table + LogicalPartition extended; + LogicalPartition nonExtended; + if (error == B_OK) { + for (int32 i = 0; error == B_OK && i < 4; i++) { + const partition_descriptor *descriptor = &fPTS->table[i]; + LogicalPartition *partition = NULL; + if (!descriptor->is_empty()) { + if (descriptor->is_extended()) { + if (extended.IsEmpty()) { + extended.SetTo(descriptor, offset, fBlockSize, + 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, fBlockSize, + primary); + partition = &nonExtended; + } else { + // only one non-extended partition allowed + error = B_BAD_DATA; + TRACE(("intel: _ParseExtended(): only one " + "non-extended partition allowed\n")); + } + } + // check the partition's location + if (partition && !partition->CheckLocation(fSessionSize, + fBlockSize)) { + error = B_BAD_DATA; + } + } + } + } + // 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 partition + if (error == B_OK && !extended.IsEmpty()) + offset = extended.Offset(); + else + break; + } + return error; +} + +// _ReadPTS +status_t +PartitionMapParser::_ReadPTS(off_t offset, partition_table_sector *pts) +{ + status_t error = B_OK; + if (!pts) + pts = fPTS; + int32 toRead = sizeof(partition_table_sector); + // check the offset + if (offset < 0 || offset + toRead > fSessionSize) { + error = B_BAD_VALUE; + TRACE(("intel: _ReadPTS(): bad offset: %Ld\n", offset)); + // read + } else if (read_pos(fDeviceFD, fSessionOffset + offset, pts, toRead) + != toRead) { +#ifndef _BOOT_MODE + error = errno; + if (error == B_OK) + error = B_IO_ERROR; +#else + error = B_IO_ERROR; +#endif + TRACE(("intel: _ReadPTS(): reading the PTS failed: %s\n", + strerror(error))); + } + return error; +} + diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h new file mode 100644 index 0000000000..3d74637a6d --- /dev/null +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.h @@ -0,0 +1,38 @@ +// PartitionMapParser.h + +#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(); + + status_t Parse(const uint8 *block, PartitionMap *map); + + 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: + int fDeviceFD; + off_t fSessionOffset; + off_t fSessionSize; + int32 fBlockSize; + partition_table_sector *fPTS; // while parsing + PartitionMap *fMap; // +}; + +#endif // PARTITION_MAP_PARSER_H diff --git a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp index 8a732e1e0f..f885e82e87 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp @@ -16,18 +16,20 @@ #include #include #include -#include #include +#include #include #ifndef _BOOT_MODE # include #else # include +//# include "DiskDeviceUtils.h" #endif #include #include "PartitionMap.h" +#include "PartitionMapParser.h" #define TRACE(x) ; //#define TRACE(x) dprintf x @@ -40,251 +42,6 @@ #define INTEL_PARTITION_NAME "Intel Partition Map" #define INTEL_EXTENDED_PARTITION_NAME "Intel Extended Partition" -// Maximal number of logical partitions per extended partition we allow. -static const int32 kMaxLogicalPartitionCount = 128; - - -// AutoDeleter - -template -class AutoDeleter { -public: - AutoDeleter(C *object) : fObject(object) {} - ~AutoDeleter() { delete fObject; } - void SetObject(C *object) { fObject = object; } - -private: - C *fObject; -}; - - -// PartitionMapParser - -class PartitionMapParser { -public: - PartitionMapParser(int deviceFD, off_t sessionOffset, off_t sessionSize, - int32 blockSize); - ~PartitionMapParser(); - - status_t Parse(const uint8 *block, PartitionMap *map); - - 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: - int fDeviceFD; - off_t fSessionOffset; - off_t fSessionSize; - int32 fBlockSize; - partition_table_sector *fPTS; // while parsing - PartitionMap *fMap; // -}; - -// constructor -PartitionMapParser::PartitionMapParser(int deviceFD, off_t sessionOffset, - off_t sessionSize, int32 blockSize) - : fDeviceFD(deviceFD), - fSessionOffset(sessionOffset), - fSessionSize(sessionSize), - fBlockSize(blockSize), - fPTS(NULL), - fMap(NULL) -{ -} - -// destructor -PartitionMapParser::~PartitionMapParser() -{ -} - -// Parse -status_t -PartitionMapParser::Parse(const uint8 *block, PartitionMap *map) -{ - status_t error = (map ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - fMap = map; - fMap->Unset(); - if (block) { - const partition_table_sector *pts - = (const partition_table_sector*)block; - error = _ParsePrimary(pts); - } else { - partition_table_sector pts; - error = _ReadPTS(0, &pts); - if (error == B_OK) - error = _ParsePrimary(&pts); - } - if (error == B_OK && !fMap->Check(fSessionSize, fBlockSize)) - error = B_BAD_DATA; - fMap = NULL; - } - return error; -} - -// _ParsePrimary -status_t -PartitionMapParser::_ParsePrimary(const partition_table_sector *pts) -{ - status_t error = (pts ? B_OK : B_BAD_VALUE); - // check the signature - if (error == B_OK && pts->signature != kPartitionTableSectorSignature) { - TRACE(("intel: _ParsePrimary(): invalid PTS signature\n")); - error = 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); - // fail, if location is bad - if (!partition->CheckLocation(fSessionSize, fBlockSize)) { - error = B_BAD_DATA; - break; - } - } - } - // allocate a PTS buffer - if (error == B_OK) { - fPTS = new(nothrow) partition_table_sector; - if (!fPTS) - error = 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()); - } - } - // cleanup - if (fPTS) { - delete fPTS; - fPTS = NULL; - } - return error; -} - -// _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 PTS - if (error == B_OK) - error = _ReadPTS(offset); - // check the signature - if (error == B_OK - && fPTS->signature != kPartitionTableSectorSignature) { - TRACE(("intel: _ParseExtended(): invalid PTS signature\n")); - error = B_BAD_DATA; - } - // ignore the PTS, if any error occured till now - if (error != B_OK) { - TRACE(("intel: _ParseExtended(): ignoring this PTS\n")); - error = B_OK; - break; - } - // examine the table - LogicalPartition extended; - LogicalPartition nonExtended; - if (error == B_OK) { - for (int32 i = 0; error == B_OK && i < 4; i++) { - const partition_descriptor *descriptor = &fPTS->table[i]; - LogicalPartition *partition = NULL; - if (!descriptor->is_empty()) { - if (descriptor->is_extended()) { - if (extended.IsEmpty()) { - extended.SetTo(descriptor, offset, fBlockSize, - 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, fBlockSize, - primary); - partition = &nonExtended; - } else { - // only one non-extended partition allowed - error = B_BAD_DATA; - TRACE(("intel: _ParseExtended(): only one " - "non-extended partition allowed\n")); - } - } - // check the partition's location - if (partition && !partition->CheckLocation(fSessionSize, - fBlockSize)) { - error = B_BAD_DATA; - } - } - } - } - // 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 partition - if (error == B_OK && !extended.IsEmpty()) - offset = extended.Offset(); - else - break; - } - return error; -} - -// _ReadPTS -status_t -PartitionMapParser::_ReadPTS(off_t offset, partition_table_sector *pts) -{ - status_t error = B_OK; - if (!pts) - pts = fPTS; - int32 toRead = sizeof(partition_table_sector); - // check the offset - if (offset < 0 || offset + toRead > fSessionSize) { - error = B_BAD_VALUE; - TRACE(("intel: _ReadPTS(): bad offset: %Ld\n", offset)); - // read - } else if (read_pos(fDeviceFD, fSessionOffset + offset, pts, toRead) - != toRead) { -#ifndef _BOOT_MODE - error = errno; - if (error == B_OK) - error = B_IO_ERROR; -#else - error = B_IO_ERROR; -#endif - TRACE(("intel: _ReadPTS(): reading the PTS failed: %s\n", - strerror(error))); - } - return error; -} - // intel partition map module @@ -308,13 +65,18 @@ static bool pm_supports_resizing_child(partition_data *partition, static bool pm_validate_resize_child(partition_data *partition, partition_data *child, off_t *size); + +// writing +static status_t pm_resize_child(int fd, partition_id partition, off_t size, + disk_job_id job); #endif #ifdef _BOOT_MODE -partition_module_info gIntelPartitionMapModule = { +partition_module_info gIntelPartitionMapModule = #else -static partition_module_info intel_partition_map_module = { +static partition_module_info intel_partition_map_module = #endif +{ { INTEL_PARTITION_MODULE_NAME, 0, @@ -369,7 +131,7 @@ static partition_module_info intel_partition_map_module = { // writing NULL, // repair NULL, // resize - NULL, // resize_child + pm_resize_child, // resize_child NULL, // move NULL, // move_child NULL, // set_name @@ -402,10 +164,11 @@ static void ep_free_partition_cookie(partition_data *partition); static void ep_free_partition_content_cookie(partition_data *partition); #ifdef _BOOT_MODE -partition_module_info gIntelExtendedPartitionModule = { +partition_module_info gIntelExtendedPartitionModule = #else -static partition_module_info intel_extended_partition_module = { +static partition_module_info intel_extended_partition_module = #endif +{ { INTEL_EXTENDED_PARTITION_MODULE_NAME, 0, @@ -548,7 +311,7 @@ static status_t pm_scan_partition(int fd, partition_data *partition, void *cookie) { - AutoDeleter deleter((PartitionMap*)cookie); + ObjectDeleter deleter((PartitionMap*)cookie); // check parameters if (fd < 0 || !partition || !cookie) return B_ERROR; @@ -603,7 +366,7 @@ TRACE(("Creating child at index %ld failed\n", index - 1)); } // keep map on success or cleanup on error if (error == B_OK) { - deleter.SetObject(NULL); + deleter.Detach(); } else { partition->content_cookie = NULL; for (int32 i = 0; i < partition->child_count; i++) { @@ -693,6 +456,41 @@ pm_validate_resize_child(partition_data *partition, partition_data *child, *size = *size / partition->block_size * partition->block_size; return true; } + +// pm_resize_child +static +status_t +pm_resize_child(int fd, partition_id partitionID, off_t size, disk_job_id job) +{ +/* + disk_device_data *device = read_lock_disk_device(partitionID); + if (!device) + return B_BAD_VALUE; + DeviceStructWriteLocker locker(device, true); + // get partition and child and out partition map structure + partition_data *partition = get_parent_partition(partitionID); + partition_data *child = get_partition(partitionID); + if (!partition || !child) + return B_BAD_VALUE; + PartitionMap *map = (PartitionMap*)partition->content_cookie; + PrimaryPartition *primary = child->cookie; + if (!map || !primary) + return B_BAD_VALUE; + // validate the new size + off_t validatedSize = size; + if (!pm_validate_resize_child(partition, child, validatedSize) + return B_BAD_VALUE; + if (child->size == validatedSize) + return B_OK; + // write the changes to disk + primary->SetSize(validatedSize); + // TODO: Write... + // TODO: PartitionMapParser into separate file, + // implement PartitionMapWriter +*/ +set_disk_device_job_error_message(job, "Resize not implemented yet."); +return B_ERROR; +} #endif // _BOOT_MODE