diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index fbb0bb3f8a..8380d87a4f 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -40,13 +40,13 @@ static const struct partition_type kPartitionTypes[] = { { 0x02, "Xenix root" }, { 0x03, "Xenix user" }, { 0x04, "FAT 16-bit (dos 3.0)" }, - { 0x05, /*"Extended Partition"*/kPartitionTypeIntelExtended }, + { 0x05, /*"Extended Partition"*/INTEL_EXTENDED_PARTITION_NAME }, { 0x06, "FAT 16-bit (dos 3.31)" }, { 0x07, "OS/2 IFS, Windows NT, Advanced Unix" }, { 0x0b, "FAT 32-bit" }, { 0x0c, "FAT 32-bit, LBA-mapped" }, { 0x0d, "FAT 16-bit, LBA-mapped" }, - { 0x0f, /*"Extended Partition, LBA-mapped"*/kPartitionTypeIntelExtended }, + { 0x0f, /*"Extended Partition, LBA-mapped"*/INTEL_EXTENDED_PARTITION_NAME }, { 0x42, "Windows 2000 marker (switches to a proprietary partition table)" }, { 0x4d, "QNX 4" }, { 0x4e, "QNX 4 2nd part" }, @@ -54,7 +54,7 @@ static const struct partition_type kPartitionTypes[] = { { 0x78, "XOSL boot loader" }, { 0x82, "Linux swapfile" }, { 0x83, "Linux native" }, - { 0x85, /*"Linux extendend partition"*/kPartitionTypeIntelExtended }, + { 0x85, /*"Linux extendend partition"*/INTEL_EXTENDED_PARTITION_NAME }, { 0xa5, "FreeBSD" }, { 0xa6, "OpenBSD" }, { 0xa7, "NextSTEP" }, @@ -62,7 +62,7 @@ static const struct partition_type kPartitionTypes[] = { { 0xa9, "NetBSD" }, { 0xab, "MacOS X boot" }, { 0xbe, "Solaris 8 boot" }, - { 0xeb, /*"BeOS"*/ kPartitionTypeBFS }, + { 0xeb, /*"BeOS"*/ BFS_NAME }, { 0, NULL } }; diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h index d5b50adc07..ad8cb545fb 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h @@ -14,6 +14,12 @@ #include #include +// These match those in DiskDeviceTypes.cpp and *must* be kept in sync. +#define INTEL_PARTITION_NAME "Intel Partition Map" +#define INTEL_EXTENDED_PARTITION_NAME "Intel Extended Partition" +#define BFS_NAME "BFS Filesystem" + + // is_empty_type static inline bool diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp index 17ed036b27..f04e34bdae 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapParser.cpp @@ -118,21 +118,25 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset) "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; @@ -168,10 +172,15 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset) if (partition && !partition->CheckLocation(fSessionSize, fBlockSize)) { error = B_BAD_DATA; + TRACE(("intel: _ParseExtended(): Invalid partition " + "location: pts: %lld, offset: %lld, size: %lld\n", + partition->PTSOffset(), partition->Offset(), + partition->Size())); } } } } + // add non-extended partition to list if (error == B_OK && !nonExtended.IsEmpty()) { LogicalPartition *partition @@ -181,12 +190,14 @@ PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset) else error = B_NO_MEMORY; } + // prepare to parse next extended partition if (error == B_OK && !extended.IsEmpty()) offset = extended.Offset(); else break; } + return error; } @@ -212,8 +223,7 @@ PartitionMapParser::_ReadPTS(off_t offset, partition_table_sector *pts) #else error = B_IO_ERROR; #endif - TRACE(("intel: _ReadPTS(): reading the PTS failed: %s\n", - strerror(error))); + TRACE(("intel: _ReadPTS(): reading the PTS failed: %lx\n", error)); } return error; } diff --git a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp index f885e82e87..f13149e8a9 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp @@ -38,9 +38,24 @@ #define INTEL_PARTITION_MODULE_NAME "partitioning_systems/intel/map/v1" #define INTEL_EXTENDED_PARTITION_MODULE_NAME "partitioning_systems/intel/extended/v1" -// these match those in DiskDeviceTypes.cpp -#define INTEL_PARTITION_NAME "Intel Partition Map" -#define INTEL_EXTENDED_PARTITION_NAME "Intel Extended Partition" +// no atomic_add() in the boot loader +#ifdef _BOOT_MODE + +inline int32 +atomic_add(int32 *a, int32 num) +{ + int32 oldA = *a; + *a += num; + return oldA; +} + +#endif + + +// A PartitionMap with reference count. +struct PartitionMapCookie : PartitionMap { + int32 ref_count; +}; // intel partition map module @@ -275,14 +290,17 @@ pm_identify_partition(int fd, partition_data *partition, void **cookie) // check parameters if (fd < 0 || !partition || !cookie) return -1; + TRACE(("intel: pm_identify_partition(%d, %ld: %lld, %lld, %ld)\n", fd, partition->id, partition->offset, partition->size, partition->block_size)); + // reject extended partitions if (partition->type && !strcmp(partition->type, kPartitionTypeIntelExtended)) { return -1; } + // check block size uint32 blockSize = partition->block_size; if (blockSize < sizeof(partition_table_sector)) { @@ -290,10 +308,13 @@ pm_identify_partition(int fd, partition_data *partition, void **cookie) ">= %ld\n", blockSize, sizeof(partition_table_sector))); return -1; } + // allocate a PartitionMap - PartitionMap *map = new(nothrow) PartitionMap; + PartitionMapCookie *map = new(nothrow) PartitionMapCookie; if (!map) return -1; + map->ref_count = 1; + // read the partition structure PartitionMapParser parser(fd, 0, partition->size, blockSize); status_t error = parser.Parse(NULL, map); @@ -301,6 +322,7 @@ pm_identify_partition(int fd, partition_data *partition, void **cookie) *cookie = map; return 0.5; } + // cleanup, if not detected delete map; return -1; @@ -311,14 +333,15 @@ static status_t pm_scan_partition(int fd, partition_data *partition, void *cookie) { - ObjectDeleter deleter((PartitionMap*)cookie); // check parameters if (fd < 0 || !partition || !cookie) return B_ERROR; + TRACE(("intel: pm_scan_partition(%d, %ld: %lld, %lld, %ld)\n", fd, partition->id, partition->offset, partition->size, partition->block_size)); - PartitionMap *map = (PartitionMap*)cookie; + + PartitionMapCookie *map = (PartitionMapCookie*)cookie; // fill in the partition_data structure partition->status = B_PARTITION_VALID; partition->flags |= B_PARTITION_PARTITIONING_SYSTEM @@ -339,7 +362,6 @@ pm_scan_partition(int fd, partition_data *partition, void *cookie) index, -1); index++; if (!child) { -TRACE(("Creating child at index %ld failed\n", index - 1)); // something went wrong error = B_ERROR; break; @@ -364,9 +386,10 @@ TRACE(("Creating child at index %ld failed\n", index - 1)); } } } + // keep map on success or cleanup on error if (error == B_OK) { - deleter.Detach(); + atomic_add(&map->ref_count, 1); } else { partition->content_cookie = NULL; for (int32 i = 0; i < partition->child_count; i++) { @@ -382,8 +405,11 @@ static void pm_free_identify_partition_cookie(partition_data */*partition*/, void *cookie) { - if (cookie) - delete (PartitionMap*)cookie; + if (cookie) { + PartitionMapCookie *map = (PartitionMapCookie*)cookie; + if (atomic_add(&map->ref_count, -1) == 1) + delete map; + } } // pm_free_partition_cookie @@ -403,7 +429,7 @@ void pm_free_partition_content_cookie(partition_data *partition) { if (partition && partition->content_cookie) { - delete (PartitionMap*)partition->content_cookie; + pm_free_identify_partition_cookie(partition, partition->content_cookie); partition->content_cookie = NULL; } } @@ -518,8 +544,10 @@ ep_identify_partition(int fd, partition_data *partition, void **cookie) // check parameters if (fd < 0 || !partition || !cookie || !partition->cookie) return -1; + TRACE(("intel: ep_identify_partition(%d, %lld, %lld, %ld)\n", fd, partition->offset, partition->size, partition->block_size)); + // our parent must be a intel partition map partition and we must have // extended partition type if (!partition->type @@ -531,6 +559,7 @@ ep_identify_partition(int fd, partition_data *partition, void **cookie) || strcmp(parent->content_type, kPartitionTypeIntel)) { return -1; } + // things seem to be in order return 0.5; } @@ -543,6 +572,10 @@ 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; @@ -566,6 +599,8 @@ ep_scan_partition(int fd, partition_data *partition, void *cookie) index++; if (!child) { // something went wrong + TRACE(("intel: ep_scan_partition(): failed to create child " + "partition\n")); error = B_ERROR; break; } @@ -576,6 +611,7 @@ ep_scan_partition(int fd, partition_data *partition, void *cookie) char type[B_FILE_NAME_LENGTH]; logical->GetTypeString(type); child->type = strdup(type); + // parameters char buffer[128]; sprintf(buffer, "type = %u ; active = %d", logical->Type(), @@ -584,6 +620,8 @@ ep_scan_partition(int fd, partition_data *partition, void *cookie) 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; }