IOReturn IOGUIDPartitionScheme::requestProbe(IOOptionBits options) { // // Request that the provider media be re-scanned for partitions. // OSSet * partitions = 0; OSSet * partitionsNew; SInt32 score = 0; // Scan the provider media for partitions. partitionsNew = scan( &score ); if ( partitionsNew ) { if ( lockForArbitration( false ) ) { partitions = juxtaposeMediaObjects( _partitions, partitionsNew ); if ( partitions ) { _partitions->release( ); _partitions = partitions; } unlockForArbitration( ); } partitionsNew->release( ); } return partitions ? kIOReturnSuccess : kIOReturnError; }
OSCollection * OSSet::copyCollection(OSDictionary *cycleDict) { bool allocDict = !cycleDict; OSCollection *ret = 0; OSSet *newSet = 0; if (allocDict) { cycleDict = OSDictionary::withCapacity(16); if (!cycleDict) return 0; } do { // Check for a cycle ret = super::copyCollection(cycleDict); if (ret) continue; // Found it newSet = OSSet::withCapacity(members->capacity); if (!newSet) continue; // Couldn't create new set abort // Insert object into cycle Dictionary cycleDict->setObject((const OSSymbol *) this, newSet); OSArray *newMembers = newSet->members; newMembers->capacityIncrement = members->capacityIncrement; // Now copy over the contents into the new duplicate for (unsigned int i = 0; i < members->count; i++) { OSObject *obj = EXT_CAST(members->array[i]); OSCollection *coll = OSDynamicCast(OSCollection, obj); if (coll) { OSCollection *newColl = coll->copyCollection(cycleDict); if (newColl) { obj = newColl; // Rely on cycleDict ref for a bit newColl->release(); } else goto abortCopy; }; newMembers->setObject(obj); }; ret = newSet; newSet = 0; } while(false); abortCopy: if (newSet) newSet->release(); if (allocDict) cycleDict->release(); return ret; }
OSSet *OSSet::withCapacity(unsigned int capacity) { OSSet *me = new OSSet; if (me && !me->initWithCapacity(capacity)) { me->release(); return 0; } return me; }
OSSet *OSSet::withSet(const OSSet *set, unsigned int capacity) { OSSet *me = new OSSet; if (me && !me->initWithSet(set, capacity)) { me->release(); return 0; } return me; }
OSSet *OSSet::withArray(const OSArray *array, unsigned int capacity) { OSSet *me = new OSSet; if (me && !me->initWithArray(array, capacity)) { me->release(); return 0; } return me; }
OSSet *OSSet::withObjects(const OSObject *objects[], unsigned int count, unsigned int capacity) { OSSet *me = new OSSet; if (me && !me->initWithObjects(objects, count, capacity)) { me->release(); return 0; } return me; }
void testIterator() { bool res = true; void *spaceCheck; OSObject *cache[numStrCache]; OSString *str = 0; const OSSymbol *symCache[numStrCache], *sym; OSDictionary *dict; OSSet *set; OSArray *array, *bigReturn; OSCollectionIterator *iter1, *iter2; int i, numSymbols, count1, count2, count3; // Setup symbol and string pools for (i = 0, numSymbols = 0; i < numStrCache; i++) { sym = OSSymbol::withCStringNoCopy(strCache[i]); if (1 == sym->getRetainCount()) { cache[numSymbols] = OSString::withCStringNoCopy(strCache[i]); symCache[numSymbols] = sym; numSymbols++; } else sym->release(); } // Test the array iterator spaceCheck = checkPointSpace(); iter1 = iter2 = 0; array = OSArray::withCapacity(numSymbols); TEST_ASSERT('I', "1a", array); if (array) { count1 = count2 = 0; for (i = numSymbols; --i >= 0; ) count1 += array->setObject(cache[i], 0); TEST_ASSERT('I', "1b", count1 == numSymbols); iter1 = OSCollectionIterator::withCollection(array); iter2 = OSCollectionIterator::withCollection(array); } TEST_ASSERT('I', "1c", iter1); TEST_ASSERT('I', "1d", iter2); if (iter1 && iter2) { count1 = count2 = count3 = 0; for (i = 0; (str = (IOString *) iter1->getNextObject()); i++) { bigReturn = iter2->nextEntries(); count1 += (bigReturn->getCount() == 1); count2 += (cache[i] == bigReturn->getObject(0)); count3 += (cache[i] == str); } TEST_ASSERT('I', "1e", count1 == numSymbols); TEST_ASSERT('I', "1f", count2 == numSymbols); TEST_ASSERT('I', "1g", count3 == numSymbols); TEST_ASSERT('I', "1h", iter1->valid()); TEST_ASSERT('I', "1i", iter2->valid()); iter1->reset(); str = (OSString *) array->__takeObject(0); array->setObject(str, 0); str->release(); TEST_ASSERT('I', "1j", !iter1->getNextObject()); TEST_ASSERT('I', "1k", !iter1->valid()); iter1->reset(); count1 = count2 = count3 = 0; for (i = 0; ; i++) { if (i & 1) str = (OSString *) iter1->getNextObject(); else if ( (bigReturn = iter1->nextEntries()) ) str = (OSString *) bigReturn->getObject(0); else str = 0; if (!str) break; count1 += (cache[i] == str); } TEST_ASSERT('I', "1l", count1 == numSymbols); TEST_ASSERT('I', "1m", i == numSymbols); TEST_ASSERT('I', "1n", iter1->valid()); TEST_ASSERT('I', "1o", 3 == array->getRetainCount()); array->release(); } if (iter1) iter1->release(); if (iter2) iter2->release(); res = res && checkSpace("(I)1", spaceCheck, 0); // Test the set iterator spaceCheck = checkPointSpace(); iter1 = 0; set = OSSet::withCapacity(numSymbols); TEST_ASSERT('I', "2a", set); if (set) { count1 = count2 = 0; for (i = 0; i < numSymbols; i++) count1 += set->setObject(cache[i]); TEST_ASSERT('I', "2b", count1 == numSymbols); iter1 = OSCollectionIterator::withCollection(set); iter2 = OSCollectionIterator::withCollection(set); } TEST_ASSERT('I', "2c", iter1); TEST_ASSERT('I', "2d", iter2); if (iter1 && iter2) { count1 = count2 = count3 = 0; for (i = 0; (str = (IOString *) iter1->getNextObject()); i++) { bigReturn = iter2->nextEntries(); count1 += (bigReturn->getCount() == 1); count2 += (cache[i] == bigReturn->getObject(0)); count3 += (cache[i] == str); } TEST_ASSERT('I', "2e", count1 == numSymbols); TEST_ASSERT('I', "2f", count2 == numSymbols); TEST_ASSERT('I', "2g", count3 == numSymbols); TEST_ASSERT('I', "2h", iter1->valid()); TEST_ASSERT('I', "2i", iter2->valid()); iter1->reset(); count1 = count2 = count3 = 0; for (i = 0; ; i++) { if (i & 1) str = (OSString *) iter1->getNextObject(); else if ( (bigReturn = iter1->nextEntries()) ) str = (OSString *) bigReturn->getObject(0); else str = 0; if (!str) break; count1 += (cache[i] == str); } TEST_ASSERT('I', "2l", count1 == numSymbols); TEST_ASSERT('I', "2m", i == numSymbols); TEST_ASSERT('I', "2n", iter1->valid()); iter1->reset(); str = (OSString *) set->getAnyObject(); (void) set->__takeObject(str); set->setObject(str); str->release(); TEST_ASSERT('I', "2j", !iter1->getNextObject()); TEST_ASSERT('I', "2k", !iter1->valid()); TEST_ASSERT('I', "2o", 3 == set->getRetainCount()); set->release(); } if (iter1) iter1->release(); if (iter2) iter2->release(); res = res && checkSpace("(I)2", spaceCheck, 0); // Test the dictionary iterator spaceCheck = checkPointSpace(); iter1 = 0; dict = OSDictionary::withCapacity(numSymbols); TEST_ASSERT('I', "3a", dict); if (dict) { count1 = count2 = 0; for (i = 0; i < numSymbols; i++) count1 += (0 != dict->setObject(cache[i], symCache[i])); TEST_ASSERT('I', "3b", count1 == numSymbols); iter1 = OSCollectionIterator::withCollection(dict); iter2 = OSCollectionIterator::withCollection(dict); } TEST_ASSERT('I', "3c", iter1); TEST_ASSERT('I', "3d", iter2); if (iter1 && iter2) { count1 = count2 = count3 = 0; for (i = 0; (sym = (const IOSymbol *) iter1->getNextObject()); i++) { bigReturn = iter2->nextEntries(); count1 += (bigReturn->getCount() == 2); count2 += (cache[i] == bigReturn->getObject(1)); count3 += (symCache[i] == sym); } TEST_ASSERT('I', "3e", count1 == numSymbols); TEST_ASSERT('I', "3f", count2 == numSymbols); TEST_ASSERT('I', "3g", count3 == numSymbols); TEST_ASSERT('I', "3h", iter1->valid()); TEST_ASSERT('I', "3i", iter2->valid()); iter1->reset(); count1 = count2 = count3 = 0; i = 0; for (i = 0; ; i++) { if (i & 1) { sym = (const OSSymbol *) iter1->getNextObject(); str = 0; } else if ( (bigReturn = iter1->nextEntries()) ) { sym = (const OSSymbol *) bigReturn->getObject(0); str = (OSString *) bigReturn->getObject(1); } else sym = 0; if (!sym) break; count1 += (symCache[i] == sym); count2 += (!str || cache[i] == str); } TEST_ASSERT('I', "3l", count1 == numSymbols); TEST_ASSERT('I', "3m", count2 == numSymbols); TEST_ASSERT('I', "3n", i == numSymbols); TEST_ASSERT('I', "3o", iter1->valid()); iter1->reset(); str = (OSString *) dict->__takeObject(symCache[numSymbols-1]); dict->setObject(str, symCache[numSymbols-1]); str->release(); TEST_ASSERT('I', "3j", !iter1->getNextObject()); TEST_ASSERT('I', "3k", !iter1->valid()); TEST_ASSERT('I', "3p", 3 == dict->getRetainCount()); dict->release(); } if (iter1) iter1->release(); if (iter2) iter2->release(); res = res && checkSpace("(I)3", spaceCheck, 0); count1 = count2 = count3 = 0; for (i = 0; i < numSymbols; i++) { count1 += (1 == cache[i]->getRetainCount()); count2 += (1 == symCache[i]->getRetainCount()); cache[i]->release(); symCache[i]->release(); } TEST_ASSERT('I', "4a", count1 == numSymbols); TEST_ASSERT('I', "4b", count2 == numSymbols); if (res) verPrintf(("testIterator: All OSCollectionIterator Tests passed\n")); else logPrintf(("testIterator: Some OSCollectionIterator Tests failed\n")); }
OSSet * IOGUIDPartitionScheme::scan(SInt32 * score) { // // Scan the provider media for a GUID partition map. Returns the set // of media objects representing each of the partitions (the retain for // the set is passed to the caller), or null should no partition map be // found. The default probe score can be adjusted up or down, based on // the confidence of the scan. // IOBufferMemoryDescriptor * buffer = 0; IOByteCount bufferSize = 0; UInt32 fdiskID = 0; disk_blk0 * fdiskMap = 0; UInt64 gptBlock = 0; UInt32 gptCheck = 0; UInt32 gptCount = 0; UInt32 gptID = 0; gpt_ent * gptMap = 0; UInt32 gptSize = 0; UInt32 headerCheck = 0; gpt_hdr * headerMap = 0; UInt32 headerSize = 0; IOMedia * media = getProvider(); UInt64 mediaBlockSize = media->getPreferredBlockSize(); bool mediaIsOpen = false; OSSet * partitions = 0; IOReturn status = kIOReturnError; // Determine whether this media is formatted. if ( media->isFormatted() == false ) goto scanErr; // Determine whether this media has an appropriate block size. if ( (mediaBlockSize % sizeof(disk_blk0)) ) goto scanErr; // Allocate a buffer large enough to hold one map, rounded to a media block. bufferSize = IORound(sizeof(disk_blk0), mediaBlockSize); buffer = IOBufferMemoryDescriptor::withCapacity( /* capacity */ bufferSize, /* withDirection */ kIODirectionIn ); if ( buffer == 0 ) goto scanErr; // Allocate a set to hold the set of media objects representing partitions. partitions = OSSet::withCapacity(8); if ( partitions == 0 ) goto scanErr; // Open the media with read access. mediaIsOpen = open(this, 0, kIOStorageAccessReader); if ( mediaIsOpen == false ) goto scanErr; // Read the protective map into our buffer. status = media->read(this, 0, buffer); if ( status != kIOReturnSuccess ) goto scanErr; fdiskMap = (disk_blk0 *) buffer->getBytesNoCopy(); // Determine whether the protective map signature is present. if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE ) { goto scanErr; } // Scan for valid partition entries in the protective map. for ( unsigned index = 0; index < DISK_NPART; index++ ) { if ( fdiskMap->parts[index].systid ) { if ( fdiskMap->parts[index].systid == 0xEE ) { if ( fdiskID ) goto scanErr; fdiskID = index + 1; } } } if ( fdiskID == 0 ) goto scanErr; // Read the partition header into our buffer. status = media->read(this, mediaBlockSize, buffer); if ( status != kIOReturnSuccess ) goto scanErr; headerMap = (gpt_hdr *) buffer->getBytesNoCopy(); // Determine whether the partition header signature is present. if ( memcmp(headerMap->hdr_sig, GPT_HDR_SIG, strlen(GPT_HDR_SIG)) ) { goto scanErr; } // Determine whether the partition header size is valid. headerCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_self); headerSize = OSSwapLittleToHostInt32(headerMap->hdr_size); if ( headerSize < offsetof(gpt_hdr, padding) ) { goto scanErr; } if ( headerSize > mediaBlockSize ) { goto scanErr; } // Determine whether the partition header checksum is valid. headerMap->hdr_crc_self = 0; if ( crc32(0, headerMap, headerSize) != headerCheck ) { goto scanErr; } // Determine whether the partition entry size is valid. gptCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_table); gptSize = OSSwapLittleToHostInt32(headerMap->hdr_entsz); if ( gptSize < sizeof(gpt_ent) ) { goto scanErr; } if ( gptSize > UINT16_MAX ) { goto scanErr; } // Determine whether the partition entry count is valid. gptBlock = OSSwapLittleToHostInt64(headerMap->hdr_lba_table); gptCount = OSSwapLittleToHostInt32(headerMap->hdr_entries); if ( gptCount > UINT16_MAX ) { goto scanErr; } // Allocate a buffer large enough to hold one map, rounded to a media block. buffer->release(); bufferSize = IORound(gptCount * gptSize, mediaBlockSize); buffer = IOBufferMemoryDescriptor::withCapacity( /* capacity */ bufferSize, /* withDirection */ kIODirectionIn ); if ( buffer == 0 ) goto scanErr; // Read the partition header into our buffer. status = media->read(this, gptBlock * mediaBlockSize, buffer); if ( status != kIOReturnSuccess ) goto scanErr; gptMap = (gpt_ent *) buffer->getBytesNoCopy(); // Determine whether the partition entry checksum is valid. if ( crc32(0, gptMap, gptCount * gptSize) != gptCheck ) { goto scanErr; } // Scan for valid partition entries in the partition map. for ( gptID = 1; gptID <= gptCount; gptID++ ) { gptMap = (gpt_ent *) ( ((UInt8 *) buffer->getBytesNoCopy()) + (gptID * gptSize) - gptSize ); uuid_unswap( gptMap->ent_type ); uuid_unswap( gptMap->ent_uuid ); if ( isPartitionUsed( gptMap ) ) { // Determine whether the partition is corrupt (fatal). if ( isPartitionCorrupt( gptMap, gptID ) ) { goto scanErr; } // Determine whether the partition is invalid (skipped). if ( isPartitionInvalid( gptMap, gptID ) ) { continue; } // Create a media object to represent this partition. IOMedia * newMedia = instantiateMediaObject( gptMap, gptID ); if ( newMedia ) { partitions->setObject(newMedia); newMedia->release(); } } } // Release our resources. close(this); buffer->release(); return partitions; scanErr: // Release our resources. if ( mediaIsOpen ) close(this); if ( partitions ) partitions->release(); if ( buffer ) buffer->release(); return 0; }
OSSet * IOFDiskPartitionScheme::scan(SInt32 * score) { // // Scan the provider media for an FDisk partition map. Returns the set // of media objects representing each of the partitions (the retain for // the set is passed to the caller), or null should no partition map be // found. The default probe score can be adjusted up or down, based on // the confidence of the scan. // IOBufferMemoryDescriptor * buffer = 0; UInt32 bufferSize = 0; UInt32 fdiskBlock = 0; UInt32 fdiskBlockExtn = 0; UInt32 fdiskBlockNext = 0; UInt32 fdiskID = 0; disk_blk0 * fdiskMap = 0; IOMedia * media = getProvider(); UInt64 mediaBlockSize = media->getPreferredBlockSize(); bool mediaIsOpen = false; OSSet * partitions = 0; IOReturn status = kIOReturnError; // Determine whether this media is formatted. if ( media->isFormatted() == false ) goto scanErr; // Determine whether this media has an appropriate block size. if ( (mediaBlockSize % sizeof(disk_blk0)) ) goto scanErr; // Allocate a buffer large enough to hold one map, rounded to a media block. bufferSize = IORound(sizeof(disk_blk0), mediaBlockSize); buffer = IOBufferMemoryDescriptor::withCapacity( /* capacity */ bufferSize, /* withDirection */ kIODirectionIn ); if ( buffer == 0 ) goto scanErr; // Allocate a set to hold the set of media objects representing partitions. partitions = OSSet::withCapacity(4); if ( partitions == 0 ) goto scanErr; // Open the media with read access. mediaIsOpen = open(this, 0, kIOStorageAccessReader); if ( mediaIsOpen == false ) goto scanErr; // Scan the media for FDisk partition map(s). do { // Read the next FDisk map into our buffer. status = media->read(this, fdiskBlock * mediaBlockSize, buffer); if ( status != kIOReturnSuccess ) goto scanErr; fdiskMap = (disk_blk0 *) buffer->getBytesNoCopy(); // Determine whether the partition map signature is present. if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE ) { goto scanErr; } // Scan for valid partition entries in the partition map. fdiskBlockNext = 0; for ( unsigned index = 0; index < DISK_NPART; index++ ) { // Determine whether this is an extended (vs. data) partition. if ( isPartitionExtended(fdiskMap->parts + index) ) // (extended) { // If peer extended partitions exist, we accept only the first. if ( fdiskBlockNext == 0 ) // (no peer extended partition) { fdiskBlockNext = fdiskBlockExtn + OSSwapLittleToHostInt32( /* data */ fdiskMap->parts[index].relsect ); if ( fdiskBlockNext * mediaBlockSize >= media->getSize() ) { fdiskBlockNext = 0; // (exceeds confines of media) } } } else if ( isPartitionUsed(fdiskMap->parts + index) ) // (data) { // Prepare this partition's ID. fdiskID = ( fdiskBlock == 0 ) ? (index + 1) : (fdiskID + 1); // Determine whether the partition is corrupt (fatal). if ( isPartitionCorrupt( /* partition */ fdiskMap->parts + index, /* partitionID */ fdiskID, /* fdiskBlock */ fdiskBlock ) ) { goto scanErr; } // Determine whether the partition is invalid (skipped). if ( isPartitionInvalid( /* partition */ fdiskMap->parts + index, /* partitionID */ fdiskID, /* fdiskBlock */ fdiskBlock ) ) { continue; } // Create a media object to represent this partition. IOMedia * newMedia = instantiateMediaObject( /* partition */ fdiskMap->parts + index, /* partitionID */ fdiskID, /* fdiskBlock */ fdiskBlock ); if ( newMedia ) { partitions->setObject(newMedia); newMedia->release(); } } } // Prepare for first extended partition, if any. if ( fdiskBlock == 0 ) { fdiskID = DISK_NPART; fdiskBlockExtn = fdiskBlockNext; } } while ( (fdiskBlock = fdiskBlockNext) ); // Release our resources. close(this); buffer->release(); return partitions; scanErr: // Release our resources. if ( mediaIsOpen ) close(this); if ( partitions ) partitions->release(); if ( buffer ) buffer->release(); return 0; }
OSSet * AppleIntelPIIXATARoot::createATAChannelNubs( void ) { OSSet * nubSet; OSDictionary * channelInfo; IORegistryEntry * dtEntry; UInt32 priChannelMode; UInt32 secChannelMode; UInt8 mapValue = 0; do { nubSet = OSSet::withCapacity(2); if ( nubSet == 0 ) break; if ( _provider->open( this ) != true ) break; priChannelMode = kChannelModePATA; secChannelMode = kChannelModePATA; // Determine SATA channel mode based on Port Mapping Register. if ( getProperty( kSerialATAKey ) == kOSBooleanTrue ) { OSString * hwName; hwName = OSDynamicCast(OSString, getProperty(kControllerNameKey)); mapValue = _provider->configRead8(kPIIX_PCI_MAP); setProperty( kPortMappingKey, mapValue, 8 ); priChannelMode = kChannelModeDisabled; secChannelMode = kChannelModeDisabled; if (hwName) { if (hwName->isEqualTo("ICH7-M SATA")) { mapValue &= 0x3; priChannelMode = gICH7MChannelModeMap[mapValue][0]; secChannelMode = gICH7MChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH6 SATA") || hwName->isEqualTo("ESB2 SATA")) { mapValue &= 0x3; priChannelMode = gICH6ChannelModeMap[mapValue][0]; secChannelMode = gICH6ChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH6-M SATA")) { mapValue &= 0x3; priChannelMode = gICH6MChannelModeMap[mapValue][0]; secChannelMode = gICH6MChannelModeMap[mapValue][1]; } else if (hwName->isEqualTo("ICH5 SATA")) { mapValue &= 0x7; priChannelMode = gICH5ChannelModeMap[mapValue][0]; secChannelMode = gICH5ChannelModeMap[mapValue][1]; } else /* if (hwName->isEqualTo("ICH7 SATA")) */ { mapValue &= 0x3; priChannelMode = gICH7ChannelModeMap[mapValue][0]; secChannelMode = gICH7ChannelModeMap[mapValue][1]; } } } if ( priChannelMode == kChannelModeDisabled && secChannelMode == kChannelModeDisabled ) { IOLog("%s: bad value (%x) in Port Mapping register", getName(), mapValue); _provider->close( this ); break; } for ( UInt32 channelID = 0; channelID < 2; channelID++ ) { UInt32 channelMode = (channelID ? secChannelMode : priChannelMode); // Create a dictionary for the channel info. Use native mode // settings if possible, else default to legacy mode. channelInfo = createNativeModeChannelInfo( channelID, channelMode ); if (channelInfo == 0) channelInfo = createLegacyModeChannelInfo( channelID, channelMode ); if (channelInfo == 0) continue; // Create a nub for each ATA channel. AppleIntelPIIXATAChannel * nub = new AppleIntelPIIXATAChannel; if ( nub ) { dtEntry = getDTChannelEntry( channelID ); if ( nub->init( this, channelInfo, dtEntry ) && nub->attach( this ) ) { nubSet->setObject( nub ); } if ( dtEntry ) { dtEntry->release(); } else { // Platform did not create a device tree entry for // this ATA channel. Do it here. char channelName[5] = {'C','H','N','_','\0'}; channelName[3] = '0' + channelID; nub->setName( channelName ); if ( _provider->inPlane(gIODTPlane) ) { nub->attachToParent( _provider, gIODTPlane ); } } nub->release(); } channelInfo->release(); } _provider->close( this ); } while ( false ); // Release and invalidate an empty set. if ( nubSet && (nubSet->getCount() == 0) ) { nubSet->release(); nubSet = 0; } return nubSet; }
OSSet * AppleNForceATARoot::createATAChannels( void ) { OSSet * nubSet; OSDictionary * channelInfo; IORegistryEntry * dtEntry; char* debugInfo; do { nubSet = OSSet::withCapacity(2); if (nubSet == 0) break; if (fProvider->open(this) != true) break; for ( UInt32 channelID = 0; channelID < 2; channelID++ ) { // Create a dictionary for the channel info. Use native mode // settings if possible, else default to legacy mode. debugInfo = "native"; channelInfo = createNativeModeChannelInfo( channelID ); if (channelInfo == 0) { debugInfo = "legacy"; channelInfo = createLegacyModeChannelInfo( channelID ); } if (channelInfo == 0) continue; DEBUG_LOG( "%s::%s() [this=%p] created channel %d in %s mode.\n", getName(), __FUNCTION__, this, (int)channelID, debugInfo ); // Create a nub for each ATA channel. AppleNForceATAChannel * nub = new AppleNForceATAChannel; if ( nub ) { dtEntry = getDTChannelEntry( channelID ); // Invoke special init method in channel nub. if (nub->init( this, channelInfo, dtEntry ) && nub->attach( this )) { nubSet->setObject( nub ); } if ( dtEntry ) { dtEntry->release(); } else { // Platform did not create a device tree entry for // this ATA channel. Do it here. char channelName[5] = {'C','H','N','_','\0'}; channelName[3] = '0' + channelID; nub->setName( channelName ); if (fProvider->inPlane(gIODTPlane)) { nub->attachToParent( fProvider, gIODTPlane ); } } nub->release(); } channelInfo->release(); } fProvider->close( this ); } while ( false ); // Release and invalidate an empty set. if (nubSet && (nubSet->getCount() == 0)) { nubSet->release(); nubSet = 0; } return nubSet; }
OSSet * IOPartitionScheme::juxtaposeMediaObjects(OSSet * partitionsOld, OSSet * partitionsNew) { // // Updates a set of existing partitions, represented by partitionsOld, // with possible updates from a rescan of the disk, represented by // partitionsNew. It returns a new set of partitions with the results, // removing partitions from partitionsOld where applicable, adding // partitions from partitionsNew where applicable, and folding in property // changes to partitions from partitionsNew into partitionsOld where // applicable. // OSIterator * iterator = 0; OSIterator * iterator1 = 0; OSIterator * iterator2 = 0; OSSymbol * key; OSSet * keys = 0; IOMedia * partition; IOMedia * partition1; IOMedia * partition2; OSSet * partitions = 0; OSOrderedSet * partitions1 = 0; OSOrderedSet * partitions2 = 0; UInt32 partitionID = 0; OSDictionary * properties; // Allocate a set to hold the set of media objects representing partitions. partitions = OSSet::withCapacity( partitionsNew->getCapacity( ) ); if ( partitions == 0 ) goto juxtaposeErr; // Prepare the reference set of partitions. partitions1 = OSOrderedSet::withCapacity( partitionsOld->getCapacity( ), partitionComparison, 0 ); if ( partitions1 == 0 ) goto juxtaposeErr; iterator1 = OSCollectionIterator::withCollection( partitionsOld ); if ( iterator1 == 0 ) goto juxtaposeErr; while ( ( partition1 = ( IOMedia * ) iterator1->getNextObject( ) ) ) { partitionID = max( partitionID, strtoul( partition1->getLocation( ), NULL, 10 ) ); partitions1->setObject( partition1 ); } iterator1->release( ); iterator1 = 0; // Prepare the comparison set of partitions. partitions2 = OSOrderedSet::withCapacity( partitionsNew->getCapacity( ), partitionComparison, 0 ); if ( partitions2 == 0 ) goto juxtaposeErr; iterator2 = OSCollectionIterator::withCollection( partitionsNew ); if ( iterator2 == 0 ) goto juxtaposeErr; while ( ( partition2 = ( IOMedia * ) iterator2->getNextObject( ) ) ) { partitionID = max( partitionID, strtoul( partition2->getLocation( ), NULL, 10 ) ); partitions2->setObject( partition2 ); } iterator2->release( ); iterator2 = 0; // Juxtapose the partitions. iterator1 = OSCollectionIterator::withCollection( partitions1 ); if ( iterator1 == 0 ) goto juxtaposeErr; iterator2 = OSCollectionIterator::withCollection( partitions2 ); if ( iterator2 == 0 ) goto juxtaposeErr; partition1 = ( IOMedia * ) iterator1->getNextObject( ); partition2 = ( IOMedia * ) iterator2->getNextObject( ); while ( partition1 || partition2 ) { UInt64 base1; UInt64 base2; base1 = partition1 ? partition1->getBase( ) : UINT64_MAX; base2 = partition2 ? partition2->getBase( ) : UINT64_MAX; #if TARGET_OS_EMBEDDED if ( partition1 && partition2 ) { OSString * uuid1; OSString * uuid2; uuid1 = OSDynamicCast( OSString, partition1->getProperty( kIOMediaUUIDKey ) ); uuid2 = OSDynamicCast( OSString, partition2->getProperty( kIOMediaUUIDKey ) ); if ( uuid1 || uuid2 ) { if ( uuid1 == 0 ) { base1 = UINT64_MAX; } else if ( uuid2 == 0 ) { base2 = UINT64_MAX; } else { int compare; compare = strcmp( uuid1->getCStringNoCopy( ), uuid2->getCStringNoCopy( ) ); if ( compare > 0 ) { base1 = UINT64_MAX; } else if ( compare < 0 ) { base2 = UINT64_MAX; } else { base1 = base2; } } } } #endif /* TARGET_OS_EMBEDDED */ if ( base1 > base2 ) { // A partition was added. partition2->setProperty( kIOMediaLiveKey, true ); iterator = OSCollectionIterator::withCollection( partitions1 ); if ( iterator == 0 ) goto juxtaposeErr; while ( ( partition = ( IOMedia * ) iterator->getNextObject( ) ) ) { if ( strcmp( partition->getLocation( ), partition2->getLocation( ) ) == 0 ) { // Set a location value for this partition. char location[ 12 ]; partitionID++; snprintf( location, sizeof( location ), "%d", ( int ) partitionID ); partition2->setLocation( location ); partition2->setProperty( kIOMediaLiveKey, false ); break; } } iterator->release( ); iterator = 0; if ( partition2->attach( this ) ) { attachMediaObjectToDeviceTree( partition2 ); partition2->registerService( kIOServiceAsynchronous ); } partitions->setObject( partition2 ); partition2 = ( IOMedia * ) iterator2->getNextObject( ); } else if ( base1 < base2 ) { // A partition was removed. partition1->setProperty( kIOMediaLiveKey, false ); if ( handleIsOpen( partition1 ) == false ) { partition1->terminate( kIOServiceSynchronous ); detachMediaObjectFromDeviceTree( partition1 ); } else { partition1->removeProperty( kIOMediaPartitionIDKey ); partitions->setObject( partition1 ); } partition1 = ( IOMedia * ) iterator1->getNextObject( ); } else { // A partition was matched. bool edit; bool move; edit = false; move = false; keys = OSSet::withCapacity( 1 ); if ( keys == 0 ) goto juxtaposeErr; properties = partition2->getPropertyTable( ); // Determine which properties were updated. if ( partition1->getBase( ) != partition2->getBase( ) || partition1->getSize( ) != partition2->getSize( ) || partition1->getPreferredBlockSize( ) != partition2->getPreferredBlockSize( ) || partition1->getAttributes( ) != partition2->getAttributes( ) || partition1->isWhole( ) != partition2->isWhole( ) || partition1->isWritable( ) != partition2->isWritable( ) || strcmp( partition1->getContentHint( ), partition2->getContentHint( ) ) ) { edit = true; } if ( strcmp( partition1->getName( ), partition2->getName( ) ) || strcmp( partition1->getLocation( ), partition2->getLocation( ) ) ) { move = true; } iterator = OSCollectionIterator::withCollection( properties ); if ( iterator == 0 ) goto juxtaposeErr; while ( ( key = ( OSSymbol * ) iterator->getNextObject( ) ) ) { OSObject * value1; OSObject * value2; if ( key->isEqualTo( kIOMediaContentHintKey ) || key->isEqualTo( kIOMediaEjectableKey ) || key->isEqualTo( kIOMediaPreferredBlockSizeKey ) || key->isEqualTo( kIOMediaRemovableKey ) || key->isEqualTo( kIOMediaSizeKey ) || key->isEqualTo( kIOMediaWholeKey ) || key->isEqualTo( kIOMediaWritableKey ) ) { continue; } if ( key->isEqualTo( kIOMediaContentKey ) || key->isEqualTo( kIOMediaLeafKey ) || key->isEqualTo( kIOMediaLiveKey ) || key->isEqualTo( kIOMediaOpenKey ) ) { continue; } value1 = partition1->getProperty( key ); value2 = partition2->getProperty( key ); if ( value1 == 0 || value1->isEqualTo( value2 ) == false ) { keys->setObject( key ); } } iterator->release( ); iterator = 0; // A partition was updated. partition1->setProperty( kIOMediaLiveKey, ( move == false ) ); if ( edit ) { partition1->init( partition2->getBase( ), partition2->getSize( ), partition2->getPreferredBlockSize( ), partition2->getAttributes( ), partition2->isWhole( ), partition2->isWritable( ), partition2->getContentHint( ) ); } if ( keys->getCount( ) ) { iterator = OSCollectionIterator::withCollection( keys ); if ( iterator == 0 ) goto juxtaposeErr; while ( ( key = ( OSSymbol * ) iterator->getNextObject( ) ) ) { partition1->setProperty( key, partition2->getProperty( key ) ); } iterator->release( ); iterator = 0; } if ( edit || keys->getCount( ) ) { partition1->messageClients( kIOMessageServicePropertyChange ); partition1->registerService( kIOServiceAsynchronous ); } keys->release( ); keys = 0; partitions->setObject( partition1 ); partition1 = ( IOMedia * ) iterator1->getNextObject( ); partition2 = ( IOMedia * ) iterator2->getNextObject( ); } } // Release our resources. iterator1->release( ); iterator2->release( ); partitions1->release( ); partitions2->release( ); return partitions; juxtaposeErr: // Release our resources. if ( iterator ) iterator->release( ); if ( iterator1 ) iterator1->release( ); if ( iterator2 ) iterator2->release( ); if ( keys ) keys->release( ); if ( partitions ) partitions->release( ); if ( partitions1 ) partitions1->release( ); if ( partitions2 ) partitions2->release( ); return 0; }
OSReturn OSMetaClass::postModLoad(void *loadHandle) { OSReturn result = kOSReturnSuccess; OSSet *kmodSet = 0; if (!sStalled || loadHandle != sStalled) { logError(kOSMetaClassInternal); return kOSMetaClassInternal; } if (sStalled->result) result = sStalled->result; else switch (sBootstrapState) { case kNoDictionaries: sBootstrapState = kMakingDictionaries; // No break; fall through case kMakingDictionaries: sKModClassesDict = OSDictionary::withCapacity(kKModCapacityIncrement); sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); if (!sAllClassesDict || !sKModClassesDict) { result = kOSMetaClassNoDicts; break; } // No break; fall through case kCompletedBootstrap: { unsigned int i; if (!sStalled->count) break; // Nothing to do so just get out // First pass checking classes aren't already loaded for (i = 0; i < sStalled->count; i++) { OSMetaClass *me = sStalled->classes[i]; if (0 != sAllClassesDict->getObject((const char *) me->className)) { printf("Class \"%s\" is duplicate\n", (const char *) me->className); result = kOSMetaClassDuplicateClass; break; } } if (i != sStalled->count) break; kmodSet = OSSet::withCapacity(sStalled->count); if (!kmodSet) { result = kOSMetaClassNoKModSet; break; } if (!sKModClassesDict->setObject(sStalled->kmodName, kmodSet)) { result = kOSMetaClassNoInsKModSet; break; } // Second pass symbolling strings and inserting classes in dictionary for (unsigned int i = 0; i < sStalled->count; i++) { OSMetaClass *me = sStalled->classes[i]; me->className = OSSymbol::withCStringNoCopy((const char *) me->className); sAllClassesDict->setObject(me->className, me); kmodSet->setObject(me); } sBootstrapState = kCompletedBootstrap; break; } default: result = kOSMetaClassInternal; break; } if (kmodSet) kmodSet->release(); if (sStalled) { ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) + sizeof(*sStalled))); kfree((vm_offset_t) sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *)); kfree((vm_offset_t) sStalled, sizeof(*sStalled)); sStalled = 0; } logError(result); mutex_unlock(loadLock); return result; }