void KLDBootstrap::readBooterExtensions(void) { IORegistryEntry * booterMemoryMap = NULL; // must release OSDictionary * propertyDict = NULL; // must release OSCollectionIterator * keyIterator = NULL; // must release OSString * deviceTreeName = NULL; // do not release const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not free char * booterDataPtr = NULL; // do not free OSData * booterData = NULL; // must release OSKext * aKext = NULL; // must release OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag, "Reading startup extensions from booter memory."); booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane); if (!booterMemoryMap) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag, "Can't read booter memory map."); goto finish; } propertyDict = booterMemoryMap->dictionaryWithProperties(); if (!propertyDict) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag, "Can't get property dictionary from memory map."); goto finish; } keyIterator = OSCollectionIterator::withCollection(propertyDict); if (!keyIterator) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag, "Can't allocate iterator for driver images."); goto finish; } /* Create dictionary of excluded kexts */ OSKext::createExcludeListFromBooterData(propertyDict, keyIterator); keyIterator->reset(); while ( ( deviceTreeName = OSDynamicCast(OSString, keyIterator->getNextObject() ))) { const char * devTreeNameCString = deviceTreeName->getCStringNoCopy(); OSData * deviceTreeEntry = OSDynamicCast(OSData, propertyDict->getObject(deviceTreeName)); /* Clear out the booterData from the prior iteration. */ OSSafeReleaseNULL(booterData); /* If there is no entry for the name, we can't do much with it. */ if (!deviceTreeEntry) { continue; } /* Make sure it is a kext */ if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX, CONST_STRLEN(BOOTER_KEXT_PREFIX))) { continue; } deviceTreeBuffer = (const _DeviceTreeBuffer *) deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer)); if (!deviceTreeBuffer) { /* We can't get to the data, so we can't do anything, * not even free it from physical memory (if it's there). */ OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag, "Device tree entry %s has NULL pointer.", devTreeNameCString); goto finish; // xxx - continue, panic? } booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr); if (!booterDataPtr) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag, "Can't get virtual address for device tree entry %s.", devTreeNameCString); goto finish; } /* Wrap the booter data buffer in an OSData and set a dealloc function * so it will take care of the physical memory when freed. Kexts will * retain the booterData for as long as they need it. Remove the entry * from the booter memory map after this is done. */ booterData = OSData::withBytesNoCopy(booterDataPtr, deviceTreeBuffer->length); if (!booterData) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag, "Error - Can't allocate OSData wrapper for device tree entry %s.", devTreeNameCString); goto finish; } booterData->setDeallocFunction(osdata_phys_free); /* Create the kext for the entry, then release it, because the * kext system keeps them around until explicitly removed. * Any creation/registration failures are already logged for us. */ OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData); OSSafeReleaseNULL(newKext); booterMemoryMap->removeProperty(deviceTreeName); } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */ finish: OSSafeReleaseNULL(booterMemoryMap); OSSafeReleaseNULL(propertyDict); OSSafeReleaseNULL(keyIterator); OSSafeReleaseNULL(booterData); OSSafeReleaseNULL(aKext); return; }
UInt32 FakeSMCKeyStore::loadKeysFromNVRAM() { UInt32 count = 0; // Find driver and load keys from NVRAM // check for Chameleon NVRAM key first (because waiting for IODTNVRAM hangs) IORegistryEntry* nvram = IORegistryEntry::fromPath("/chosen/nvram", gIODTPlane); OSDictionary* matching = 0; if (!nvram) { // probably booting w/ Clover matching = serviceMatching("IODTNVRAM"); if (matching) nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15)); } if (1) { //REVIEW_REHAB: ease of merging... if (nvram) { useNVRAM = true; if ((genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", sizeof("AppleNVRAM"))))) HWSensorsInfoLog("fallback to generic NVRAM methods"); OSSerialize *s = OSSerialize::withCapacity(0); // Workaround for IODTNVRAM->getPropertyTable returns IOKitPersonalities instead of NVRAM properties dictionary if (nvram->serializeProperties(s)) { if (OSDictionary *props = OSDynamicCast(OSDictionary, OSUnserializeXML(s->text()))) { if (OSCollectionIterator *iterator = OSCollectionIterator::withCollection(props)) { size_t prefix_length = strlen(kFakeSMCKeyPropertyPrefix); char name[5]; name[4] = 0; char type[5]; type[4] = 0; while (OSString *property = OSDynamicCast(OSString, iterator->getNextObject())) { const char *buffer = static_cast<const char *>(property->getCStringNoCopy()); if (property->getLength() >= prefix_length + 1 + 4 + 1 + 0 && 0 == strncmp(buffer, kFakeSMCKeyPropertyPrefix, prefix_length)) { if (OSData *data = OSDynamicCast(OSData, props->getObject(property))) { strncpy(name, buffer + prefix_length + 1, 4); // fakesmc-key-???? -> strncpy(type, buffer + prefix_length + 1 + 4 + 1, 4); // fakesmc-key-xxxx-???? -> if (addKeyWithValue(name, type, data->getLength(), data->getBytesNoCopy())) { HWSensorsDebugLog("key %s of type %s loaded from NVRAM", name, type); count++; } } } } OSSafeRelease(iterator); } OSSafeRelease(props); } } OSSafeRelease(s); OSSafeRelease(nvram); } else { HWSensorsWarningLog("NVRAM is unavailable"); } OSSafeRelease(matching); } return count; }
void KLDBootstrap::readPrelinkedExtensions( kernel_section_t * prelinkInfoSect) { OSArray * infoDictArray = NULL; // do not release OSObject * parsedXML = NULL; // must release OSDictionary * prelinkInfoDict = NULL; // do not release OSString * errorString = NULL; // must release OSKext * theKernel = NULL; // must release kernel_segment_command_t * prelinkTextSegment = NULL; // see code kernel_segment_command_t * prelinkInfoSegment = NULL; // see code /* We make some copies of data, but if anything fails we're basically * going to fail the boot, so these won't be cleaned up on error. */ void * prelinkData = NULL; // see code vm_size_t prelinkLength = 0; OSDictionary * infoDict = NULL; // do not release IORegistryEntry * registryRoot = NULL; // do not release OSNumber * prelinkCountObj = NULL; // must release u_int i = 0; #if NO_KEXTD bool ramDiskBoot; bool developerDevice; bool dontLoad; #endif OSData * kaslrOffsets = NULL; unsigned long plk_segSizes[PLK_SEGMENTS]; vm_offset_t plk_segAddrs[PLK_SEGMENTS]; OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Starting from prelinked kernel."); prelinkTextSegment = getsegbyname(kPrelinkTextSegment); if (!prelinkTextSegment) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Can't find prelinked kexts' text segment."); goto finish; } #if KASLR_KEXT_DEBUG unsigned long scratchSize; vm_offset_t scratchAddr; IOLog("kaslr: prelinked kernel address info: \n"); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__TEXT", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__DATA", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__LINKEDIT", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__KLD", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_TEXT", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_INFO", &scratchSize); IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n", (unsigned long)scratchAddr, (unsigned long)(scratchAddr + scratchSize), scratchSize); #endif prelinkData = (void *) prelinkTextSegment->vmaddr; prelinkLength = prelinkTextSegment->vmsize; /* build arrays of plk info for later use */ const char ** segNamePtr; for (segNamePtr = &plk_segNames[0], i = 0; *segNamePtr && i < PLK_SEGMENTS; segNamePtr++, i++) { plk_segSizes[i] = 0; plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(&_mh_execute_header, *segNamePtr, &plk_segSizes[i]); } /* Unserialize the info dictionary from the prelink info section. */ parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr, &errorString); if (parsedXML) { prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML); } if (!prelinkInfoDict) { const char * errorCString = "(unknown error)"; if (errorString && errorString->getCStringNoCopy()) { errorCString = errorString->getCStringNoCopy(); } else if (parsedXML) { errorCString = "not a dictionary"; } OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "Error unserializing prelink plist: %s.", errorCString); goto finish; } #if NO_KEXTD /* Check if we should keep developer kexts around. * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201> */ developerDevice = true; PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice)); ramDiskBoot = IORamDiskBSDRoot(); #endif /* NO_KEXTD */ infoDictArray = OSDynamicCast(OSArray, prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey)); if (!infoDictArray) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "The prelinked kernel has no kext info dictionaries"); goto finish; } /* kaslrOffsets are available use them to slide local relocations */ kaslrOffsets = OSDynamicCast(OSData, prelinkInfoDict->getObject(kPrelinkLinkKASLROffsetsKey)); /* Create dictionary of excluded kexts */ OSKext::createExcludeListFromPrelinkInfo(infoDictArray); /* Create OSKext objects for each info dictionary. */ for (i = 0; i < infoDictArray->getCount(); ++i) { infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i)); if (!infoDict) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Can't find info dictionary for prelinked kext #%d.", i); continue; } #if NO_KEXTD dontLoad = false; /* If we're not on a developer device, skip and free developer kexts. */ if (developerDevice == false) { OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean, infoDict->getObject(kOSBundleDeveloperOnlyKey)); if (devOnlyBool == kOSBooleanTrue) { dontLoad = true; } } /* Skip and free kexts that are only needed when booted from a ram disk. */ if (ramDiskBoot == false) { OSBoolean *ramDiskOnlyBool = OSDynamicCast(OSBoolean, infoDict->getObject(kOSBundleRamDiskOnlyKey)); if (ramDiskOnlyBool == kOSBooleanTrue) { dontLoad = true; } } if (dontLoad == true) { OSString *bundleID = OSDynamicCast(OSString, infoDict->getObject(kCFBundleIdentifierKey)); if (bundleID) { OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag, "Kext %s not loading.", bundleID->getCStringNoCopy()); } OSNumber *addressNum = OSDynamicCast(OSNumber, infoDict->getObject(kPrelinkExecutableLoadKey)); OSNumber *lengthNum = OSDynamicCast(OSNumber, infoDict->getObject(kPrelinkExecutableSizeKey)); if (addressNum && lengthNum) { #error Pick the right way to free prelinked data on this arch } infoDictArray->removeObject(i--); continue; } #endif /* NO_KEXTD */ /* Create the kext for the entry, then release it, because the * kext system keeps them around until explicitly removed. * Any creation/registration failures are already logged for us. */ OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict, (kaslrOffsets ? TRUE : FALSE)); OSSafeReleaseNULL(newKext); } /* slide kxld relocations */ if (kaslrOffsets && vm_kernel_slide > 0) { int slidKextAddrCount = 0; int badSlideAddr = 0; int badSlideTarget = 0; kaslrPackedOffsets * myOffsets = NULL; myOffsets = (kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy(); for (uint32_t j = 0; j < myOffsets->count; j++) { uint64_t slideOffset = (uint64_t) myOffsets->offsetsArray[j]; uintptr_t * slideAddr = (uintptr_t *) ((uint64_t)prelinkData + slideOffset); int slideAddrSegIndex = -1; int addrToSlideSegIndex = -1; slideAddrSegIndex = __whereIsAddr( (vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS ); if (slideAddrSegIndex >= 0) { addrToSlideSegIndex = __whereIsAddr( (vm_offset_t)(*slideAddr + vm_kernel_slide), &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS ); if (addrToSlideSegIndex < 0) { badSlideTarget++; continue; } } else { badSlideAddr++; continue; } slidKextAddrCount++; *(slideAddr) += vm_kernel_slide; } // for ... /* All kexts are now slid, set VM protections for them */ OSKext::setAllVMAttributes(); } /* Store the number of prelinked kexts in the registry so we can tell * when the system has been started from a prelinked kernel. */ registryRoot = IORegistryEntry::getRegistryRoot(); assert(registryRoot); prelinkCountObj = OSNumber::withNumber( (unsigned long long)infoDictArray->getCount(), 8 * sizeof(uint32_t)); assert(prelinkCountObj); if (prelinkCountObj) { registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj); } OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "%u prelinked kexts", infoDictArray->getCount()); #if CONFIG_KEXT_BASEMENT /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own * special VM region during OSKext init time, so we can free the whole * segment now. */ ml_static_mfree((vm_offset_t) prelinkData, prelinkLength); #endif /* __x86_64__ */ /* Free the prelink info segment, we're done with it. */ prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment); if (prelinkInfoSegment) { ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr, (vm_size_t)prelinkInfoSegment->vmsize); } finish: OSSafeReleaseNULL(errorString); OSSafeReleaseNULL(parsedXML); OSSafeReleaseNULL(theKernel); OSSafeReleaseNULL(prelinkCountObj); return; }
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; }
static void createNubs(IOService *provider) { const char nameID[2][8] = {"@0,name", "@1,name"}; const char name[11] = "Aty,Radeon"; const char typeID[2][15] = {"@0,device_type", "@1,device_type"}; const char type[] = "display"; OSObject *tempObj; int i; if (provider->getProperty(kIONDRVIgnoreKey)) return; provider->setProperty(kIONDRVIgnoreKey, kOSBooleanTrue); //prevent IONDRVFramebuffer from match LOG("createNubs\n"); if (!provider->getProperty("@0,name") && !provider->getProperty("@1,name")) { for (i = 0;i < 2;i++) { // Debug tempObj = OSData::withBytes(name, 11); provider->setProperty(nameID[i], tempObj); tempObj->release(); tempObj = OSData::withBytes(type, 8); provider->setProperty(typeID[i], tempObj); tempObj->release(); } } // have to move below part from IONDRVFramebuffer to make it work IORegistryIterator * iter; IORegistryEntry * next; IOService * newNub; OSArray * toDo = 0; bool firstLevel; OSData * data; if (provider->getProperty("@0,name")) { OSDictionary * dict; OSCollectionIterator * keys; const OSSymbol * key; char buffer[80]; const char * keyChrs; size_t len; char c; dict = provider->dictionaryWithProperties(); keys = OSCollectionIterator::withCollection(dict); if (dict) dict->release(); if (keys) { while ((key = OSDynamicCast(OSSymbol, keys->getNextObject()))) { keyChrs = key->getCStringNoCopy(); if ('@' != keyChrs[0]) continue; len = 0; do { c = keyChrs[len]; if (!c || (c == ',')) break; buffer[len] = c; len++; } while (len < (sizeof(buffer) - 1)); if (!c) continue; buffer[len] = 0; keyChrs += len + 1; next = provider->childFromPath(buffer, gIODTPlane); if (!next) { next = new IOService; if (next && !next->init()) { next->release(); next = 0; } if (!next) continue; next->setLocation(&buffer[1]); if (!next->attachToParent(provider, gIODTPlane)) continue; } OSObject * obj = dict->getObject(key); next->setProperty(keyChrs, dict->getObject(key)); if (!strcmp(keyChrs, "name")) { OSData * data = OSDynamicCast(OSData, obj); if (data) next->setName((const char *) data->getBytesNoCopy()); } next->release(); provider->removeProperty(key); } keys->release(); } } iter = IORegistryIterator::iterateOver( provider, gIODTPlane, 0 ); toDo = OSArray::withCapacity(2); if (iter && toDo) { bool haveDoneLibInit = false; UInt32 index = 0; do { while ((next = (IORegistryEntry *) iter->getNextObject())) { firstLevel = (provider == next->getParentEntry(gIODTPlane)); if (firstLevel) { data = OSDynamicCast( OSData, next->getProperty("device_type")); if (!data || (0 != strcmp("display", (char *) data->getBytesNoCopy()))) continue; if (!haveDoneLibInit) { haveDoneLibInit = (kIOReturnSuccess == _IONDRVLibrariesInitialize(provider)); if (!haveDoneLibInit) continue; } next->setProperty( kIOFBDependentIDKey, (uintptr_t) provider, 64 ); next->setProperty( kIOFBDependentIndexKey, index, 32 ); next->setProperty( kIONDRVIgnoreKey, kOSBooleanTrue ); index++; } toDo->setObject( next ); iter->enterEntry(); } } while (iter->exitEntry()); } if (iter) iter->release(); if (toDo) { OSObject * obj; OSArray * deviceMemory; obj = provider->copyProperty(gIODeviceMemoryKey); deviceMemory = OSDynamicCast(OSArray, obj); for (unsigned int i = 0; (next = (IORegistryEntry *) toDo->getObject(i)); i++) { newNub = new IONDRVDevice; if (!newNub) continue; if (!newNub->init(next, gIODTPlane)) { newNub->free(); newNub = 0; continue; } if (deviceMemory) newNub->setDeviceMemory(deviceMemory); newNub->attach(provider); newNub->registerService(kIOServiceSynchronous); } if (obj) obj->release(); toDo->release(); } }
// ---------------------------------------------------------------------------------------------------- bool PlatformInterfaceI2S_Mapped::init (IOService* device, AppleOnboardAudio* provider, UInt32 inDBDMADeviceIndex ) { bool result = FALSE; IOService* theService; IORegistryEntry *macio; IORegistryEntry *gpio; IORegistryEntry *i2s; IORegistryEntry *i2sParent; IOMemoryMap *map; debugIOLog ( 3, "+ PlatformInterfaceI2S_Mapped::init ( IOService * device %p, AppleOnboardAudio * provider %p, UInt32 inDBDMADeviceIndex %d )", device, provider, inDBDMADeviceIndex ); FailIf ( NULL == provider, Exit ); FailIf ( NULL == device, Exit ); mProvider = provider; result = super::init ( device, provider, inDBDMADeviceIndex ); if ( result ) { mKeyLargoService = IOService::waitForService ( IOService::serviceMatching ( "KeyLargo" ) ); debugIOLog ( 3, " device name is %s", ( (IORegistryEntry*)device)->getName () ); i2s = ( ( IORegistryEntry*)device)->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2s, result = false, Exit ); debugIOLog ( 3, " parent name is '%s'", i2s->getName () ); if ( 0 == strcmp ( "i2s-a", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell0; } else if ( 0 == strcmp ( "i2s-b", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell1; } else if ( 0 == strcmp ( "i2s-c", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell2; } else if ( 0 == strcmp ( "i2s-d", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell3; } else if ( 0 == strcmp ( "i2s-e", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell4; } else if ( 0 == strcmp ( "i2s-f", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell5; } else if ( 0 == strcmp ( "i2s-g", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell6; } else if ( 0 == strcmp ( "i2s-h", i2s->getName () ) ) { mI2SInterfaceNumber = kUseI2SCell7; } debugIOLog ( 5, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber ); i2sParent = i2s->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == i2sParent, result = false, Exit ); debugIOLog ( 3, " parent name of '%s' is %s", i2s->getName (), i2sParent->getName () ); macio = i2sParent->getParentEntry ( gIODTPlane ); FailWithAction ( 0 == macio, result = false, Exit ); debugIOLog ( 3, " macio's name is %s", macio->getName () ); gpio = macio->childFromPath ( kGPIODTEntry, gIODTPlane); FailWithAction ( !gpio, result = false, Exit); debugIOLog ( 3, " gpio's name is %s", gpio->getName () ); theService = ( OSDynamicCast ( IOService, i2s ) ); FailWithAction ( !theService, result = false, Exit ); map = theService->mapDeviceMemoryWithIndex ( inDBDMADeviceIndex ); FailWithAction ( 0 == map, result = false, Exit ); // cache the config space mSoundConfigSpace = (UInt8 *)map->getPhysicalAddress(); // sets the clock base address figuring out which I2S cell we're on if ((((UInt32)mSoundConfigSpace ^ kI2S0BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S0BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S0BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell0; } else if ((((UInt32)mSoundConfigSpace ^ kI2S1BaseOffset) & 0x0001FFFF) == 0) { // [3060321] ioBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOBaseAddress = (void *)((UInt32)mSoundConfigSpace - kI2S1BaseOffset); mIOBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace - kI2S1BaseOffset), 256); mI2SInterfaceNumber = kUseI2SCell1; } else { debugIOLog (3, " AudioI2SControl::init ERROR: unable to setup ioBaseAddress and i2SInterfaceNumber"); } FailIf (NULL == mIOBaseAddressMemory, Exit); // [3060321] ioConfigurationBaseAddress is required by this object in order to enable the target // I2S I/O Module for which this object is to service. The I2S I/O Module // enable occurs through the configuration registers which reside in the // first block of ioBase. rbm 2 Oct 2002 mIOConfigurationBaseAddress = (void *)mIOBaseAddressMemory->map()->getVirtualAddress(); FailIf ( NULL == mIOConfigurationBaseAddress, Exit ); // // There are three sections of memory mapped I/O that are directly accessed by the Apple02Audio. These // include the GPIOs, I2S DMA Channel Registers and I2S control registers. They fall within the memory map // as follows: // ~ ~ // |______________________________| // | | // | I2S Control | // |______________________________| <- soundConfigSpace = ioBase + i2s0BaseOffset ...OR... ioBase + i2s1BaseOffset // | | // ~ ~ // ~ ~ // |______________________________| // | | // | I2S DMA Channel | // |______________________________| <- i2sDMA = ioBase + i2s0_DMA ...OR... ioBase + i2s1_DMA // | | // ~ ~ // ~ ~ // |______________________________| // | FCRs | // | GPIO | <- gpio = ioBase + gpioOffsetAddress // | ExtIntGPIO | <- fcr = ioBase + fcrOffsetAddress // |______________________________| <- ioConfigurationBaseAddress // | | // ~ ~ // // The I2S DMA Channel is mapped in by the Apple02DBDMAAudioDMAEngine. Only the I2S control registers are // mapped in by the AudioI2SControl. The Apple I/O Configuration Space (i.e. FCRs, GPIOs and ExtIntGPIOs) // are mapped in by the subclass of Apple02Audio. The FCRs must also be mapped in by the AudioI2SControl // object as the init method must enable the I2S I/O Module for which the AudioI2SControl object is // being instantiated for. // // Map the I2S configuration registers mIOI2SBaseAddressMemory = IODeviceMemory::withRange ((IOPhysicalAddress)((UInt8 *)mSoundConfigSpace), kI2S_IO_CONFIGURATION_SIZE); FailIf ( NULL == mIOI2SBaseAddressMemory, Exit ); mI2SBaseAddress = (void *)mIOI2SBaseAddressMemory->map()->getVirtualAddress(); FailIf (NULL == mI2SBaseAddress, Exit); debugIOLog (3, " mI2SInterfaceNumber = %d", mI2SInterfaceNumber); debugIOLog (3, " mIOI2SBaseAddressMemory = %p", mIOI2SBaseAddressMemory); debugIOLog (3, " mI2SBaseAddress = %p", mI2SBaseAddress); debugIOLog (3, " mIOBaseAddressMemory = %p", mIOBaseAddressMemory); debugIOLog (3, " mIOConfigurationBaseAddress = %p", mIOConfigurationBaseAddress); } Exit: debugIOLog ( 3, "- PlatformInterfaceI2S_Mapped::init ( IOService * device %p, AppleOnboardAudio * provider%p, UInt32 inDBDMADeviceIndex %d ) returns %lX", device, provider, inDBDMADeviceIndex, result ); return result; }
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; }
void KLDBootstrap::readPrelinkedExtensions( kernel_section_t * prelinkInfoSect) { OSArray * infoDictArray = NULL; // do not release OSArray * personalitiesArray = NULL; // do not release OSObject * parsedXML = NULL; // must release OSDictionary * prelinkInfoDict = NULL; // do not release OSString * errorString = NULL; // must release OSKext * theKernel = NULL; // must release #if CONFIG_KXLD kernel_section_t * kernelLinkStateSection = NULL; // see code #endif kernel_segment_command_t * prelinkLinkStateSegment = NULL; // see code kernel_segment_command_t * prelinkTextSegment = NULL; // see code kernel_segment_command_t * prelinkInfoSegment = NULL; // see code /* We make some copies of data, but if anything fails we're basically * going to fail the boot, so these won't be cleaned up on error. */ void * prelinkData = NULL; // see code void * prelinkCopy = NULL; // see code vm_size_t prelinkLength = 0; #if !__LP64__ && !defined(__arm__) vm_map_offset_t prelinkDataMapOffset = 0; #endif kern_return_t mem_result = KERN_SUCCESS; OSDictionary * infoDict = NULL; // do not release IORegistryEntry * registryRoot = NULL; // do not release OSNumber * prelinkCountObj = NULL; // must release u_int i = 0; OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Starting from prelinked kernel."); /***** * Wrap the kernel link state in-place in an OSData. * This is unnecessary (and the link state may not be present) if the kernel * does not have kxld support because this information is only used for * runtime linking. */ #if CONFIG_KXLD kernelLinkStateSection = getsectbyname(kPrelinkLinkStateSegment, kPrelinkKernelLinkStateSection); if (!kernelLinkStateSection) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "Can't find prelinked kernel link state."); goto finish; } theKernel = OSKext::lookupKextWithIdentifier(kOSKextKernelIdentifier); if (!theKernel) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "Can't find kernel kext object in prelinked kernel."); goto finish; } prelinkData = (void *) kernelLinkStateSection->addr; prelinkLength = kernelLinkStateSection->size; mem_result = kmem_alloc_pageable(kernel_map, (vm_offset_t *) &prelinkCopy, prelinkLength); if (mem_result != KERN_SUCCESS) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, "Can't copy prelinked kernel link state."); goto finish; } memcpy(prelinkCopy, prelinkData, prelinkLength); theKernel->linkState = OSData::withBytesNoCopy(prelinkCopy, prelinkLength); if (!theKernel->linkState) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, "Can't create prelinked kernel link state wrapper."); goto finish; } theKernel->linkState->setDeallocFunction(osdata_kmem_free); #endif prelinkTextSegment = getsegbyname(kPrelinkTextSegment); if (!prelinkTextSegment) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Can't find prelinked kexts' text segment."); goto finish; } prelinkData = (void *) prelinkTextSegment->vmaddr; prelinkLength = prelinkTextSegment->vmsize; #if !__LP64__ /* To enable paging and write/execute protections on the kext * executables, we need to copy them out of the booter-created * memory, reallocate that space with VM, then prelinkCopy them back in. * This isn't necessary on LP64 because kexts have their own VM * region on that architecture model. */ mem_result = kmem_alloc(kernel_map, (vm_offset_t *)&prelinkCopy, prelinkLength); if (mem_result != KERN_SUCCESS) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, "Can't copy prelinked kexts' text for VM reassign."); goto finish; } /* Copy it out. */ memcpy(prelinkCopy, prelinkData, prelinkLength); /* Dump the booter memory. */ ml_static_mfree((vm_offset_t)prelinkData, prelinkLength); /* Set up the VM region. */ prelinkDataMapOffset = (vm_map_offset_t)(uintptr_t)prelinkData; mem_result = vm_map_enter_mem_object( kernel_map, &prelinkDataMapOffset, prelinkLength, /* mask */ 0, VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, (ipc_port_t)NULL, (vm_object_offset_t) 0, /* copy */ FALSE, /* cur_protection */ VM_PROT_ALL, /* max_protection */ VM_PROT_ALL, /* inheritance */ VM_INHERIT_DEFAULT); if ((mem_result != KERN_SUCCESS) || (prelinkTextSegment->vmaddr != prelinkDataMapOffset)) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogArchiveFlag, "Can't create kexts' text VM entry at 0x%llx, length 0x%x (error 0x%x).", (unsigned long long) prelinkDataMapOffset, prelinkLength, mem_result); goto finish; } prelinkData = (void *)(uintptr_t)prelinkDataMapOffset; /* And copy it back. */ memcpy(prelinkData, prelinkCopy, prelinkLength); kmem_free(kernel_map, (vm_offset_t)prelinkCopy, prelinkLength); #endif /* !__LP64__ */ /* Unserialize the info dictionary from the prelink info section. */ parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr, &errorString); if (parsedXML) { prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML); } if (!prelinkInfoDict) { const char * errorCString = "(unknown error)"; if (errorString && errorString->getCStringNoCopy()) { errorCString = errorString->getCStringNoCopy(); } else if (parsedXML) { errorCString = "not a dictionary"; } OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "Error unserializing prelink plist: %s.", errorCString); goto finish; } infoDictArray = OSDynamicCast(OSArray, prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey)); if (!infoDictArray) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "The prelinked kernel has no kext info dictionaries"); goto finish; } /* Create OSKext objects for each info dictionary. */ for (i = 0; i < infoDictArray->getCount(); ++i) { infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i)); if (!infoDict) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "Can't find info dictionary for prelinked kext #%d.", i); continue; } /* Create the kext for the entry, then release it, because the * kext system keeps them around until explicitly removed. * Any creation/registration failures are already logged for us. */ OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict); OSSafeReleaseNULL(newKext); } /* Get all of the personalities for kexts that were not prelinked and * add them to the catalogue. */ personalitiesArray = OSDynamicCast(OSArray, prelinkInfoDict->getObject(kPrelinkPersonalitiesKey)); if (!personalitiesArray) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag, "The prelinked kernel has no personalities array"); goto finish; } if (personalitiesArray->getCount()) { OSKext::setPrelinkedPersonalities(personalitiesArray); } /* Store the number of prelinked kexts in the registry so we can tell * when the system has been started from a prelinked kernel. */ registryRoot = IORegistryEntry::getRegistryRoot(); assert(registryRoot); prelinkCountObj = OSNumber::withNumber( (unsigned long long)infoDictArray->getCount(), 8 * sizeof(uint32_t)); assert(prelinkCountObj); if (prelinkCountObj) { registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj); } OSSafeReleaseNULL(prelinkCountObj); prelinkCountObj = OSNumber::withNumber( (unsigned long long)personalitiesArray->getCount(), 8 * sizeof(uint32_t)); assert(prelinkCountObj); if (prelinkCountObj) { registryRoot->setProperty(kOSPrelinkPersonalityCountKey, prelinkCountObj); } OSKextLog(/* kext */ NULL, kOSKextLogProgressLevel | kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag | kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag, "%u prelinked kexts, and %u additional personalities.", infoDictArray->getCount(), personalitiesArray->getCount()); #if __LP64__ /* On LP64 systems, kexts are copied to their own special VM region * during OSKext init time, so we can free the whole segment now. */ ml_static_mfree((vm_offset_t) prelinkData, prelinkLength); #endif /* __LP64__ */ /* Free the link state segment, kexts have copied out what they need. */ prelinkLinkStateSegment = getsegbyname(kPrelinkLinkStateSegment); if (prelinkLinkStateSegment) { ml_static_mfree((vm_offset_t)prelinkLinkStateSegment->vmaddr, (vm_size_t)prelinkLinkStateSegment->vmsize); } /* Free the prelink info segment, we're done with it. */ prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment); if (prelinkInfoSegment) { ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr, (vm_size_t)prelinkInfoSegment->vmsize); } finish: OSSafeRelease(errorString); OSSafeRelease(parsedXML); OSSafeRelease(theKernel); OSSafeRelease(prelinkCountObj); return; }
// Class probe IOService * VoodooPState::probe(IOService * provider, SInt32 * score) { Ready = false; // Probe the superclass if (IOService::probe(provider, score) != this) return NULL; // Read our own values from the property list OSDictionary * dictionary = OSDynamicCast(OSDictionary, getProperty(keyPowerControl)); if (!dictionary) return NULL; UseEfiFsb = getPlistValue(dictionary, keyUseEfiFsb); VoltageOverride = getPlistValue(dictionary, keyVoltageOverride); VoltageProbe = getPlistValue(dictionary, keyVoltageProbe); UserVoltageMax = getPlistValue(dictionary, keyUserVoltageMax); UserVoltageMin = getPlistValue(dictionary, keyUserVoltageMin); ColdStart = getPlistValue(dictionary, keyColdStart); TimerInterval = getPlistValue(dictionary, keyTimerInterval); UseACPI = getPlistValue(dictionary, keyUseACPI); if(TimerInterval < 50){ TimerInterval = 50; } // Get CPU's from I/O Kit CpuCount = getCpuCount(); // No CPU's found -> bailout if (CpuCount == 0) return NULL; // Get FSB from /efi/platform CpuFSB = gPEClockFrequencyInfo.bus_frequency_max_hz >> 2; if (UseEfiFsb) { IORegistryEntry * entry = fromPath(keyEfiPlatform, gIODTPlane); if (entry) { OSObject * object = entry->getProperty(keyEfiFsbFrequency); if (object && (OSTypeIDInst(object) == OSTypeID(OSData))) { OSData * data = OSDynamicCast(OSData, object); if (data) { CpuFSB = * (UInt32 *) data->getBytesNoCopy(); gPEClockFrequencyInfo.bus_frequency_max_hz = CpuFSB << 2; } } } } CpuFSB = (CpuFSB+Mega/2) / Mega; // Mega is enough #if SUPPORT_VOODOO_KERNEL { UInt64 magic; nanoseconds_to_absolutetime(~(0), &magic); VoodooKernel = (magic == 2); } #endif // Enumerate CPU's CpuCoreTech = Unknown; { uint32_t data[4]; do_cpuid(0, data); ((uint32_t*)vendor)[0] = data[1]; ((uint32_t*)vendor)[1] = data[3]; ((uint32_t*)vendor)[2] = data[2]; vendor[15] = 0; do_cpuid(1, data); CpuSignature = data[0]; // Features ((uint32_t*)&Features)[0] = data[3]; ((uint32_t*)&Features)[1] = data[2]; for( int i = 0; i < 3; i++ ){ do_cpuid(0x80000002+i, data); memcpy( &brand_string[i*16], data, 16 ); } brand_string[16*3] = 0; } // Find core technology and cross core vendor specifics // Intel if (!strncmp(vendor, CPUID_VID_INTEL, sizeof(CPUID_VID_INTEL))) { if(!intel_probe(this)) return NULL; } // AMD else if (!strncmp(vendor, CPUID_VID_AMD, sizeof(CPUID_VID_AMD))) { if(!amd_probe(this)) return NULL; } // Unknown CPU or core technology else { ErrorLog("CPU: Core Technology Unknown - Signature %x (%s)(%s)", (unsigned int)CpuSignature, vendor, brand_string); return NULL; } return this; }
IORegistryEntry * IODeviceTreeAlloc( void * dtTop ) { IORegistryEntry * parent; IORegistryEntry * child; IORegistryIterator * regIter; DTEntryIterator iter; DTEntry dtChild; DTEntry mapEntry; OSArray * stack; OSData * prop; OSDictionary * allInts; vm_offset_t * dtMap; unsigned int propSize; bool intMap; bool freeDT; gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane ); gIODTNameKey = OSSymbol::withCStringNoCopy( "name" ); gIODTUnitKey = OSSymbol::withCStringNoCopy( "AAPL,unit-string" ); gIODTCompatibleKey = OSSymbol::withCStringNoCopy( "compatible" ); gIODTTypeKey = OSSymbol::withCStringNoCopy( "device_type" ); gIODTModelKey = OSSymbol::withCStringNoCopy( "model" ); gIODTSizeCellKey = OSSymbol::withCStringNoCopy( "#size-cells" ); gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" ); gIODTRangeKey = OSSymbol::withCStringNoCopy( "ranges" ); gIODTPersistKey = OSSymbol::withCStringNoCopy( "IODTPersist" ); assert( gIODTPlane && gIODTCompatibleKey && gIODTTypeKey && gIODTModelKey && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey && gIODTPersistKey ); gIODTDefaultInterruptController = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController"); gIODTNWInterruptMappingKey = OSSymbol::withCStringNoCopy("IONWInterrupts"); gIODTAAPLInterruptsKey = OSSymbol::withCStringNoCopy("AAPL,interrupts"); gIODTPHandleKey = OSSymbol::withCStringNoCopy("AAPL,phandle"); gIODTInterruptParentKey = OSSymbol::withCStringNoCopy("interrupt-parent"); gIODTPHandles = OSArray::withCapacity( 1 ); gIODTPHandleMap = OSArray::withCapacity( 1 ); gIODTInterruptCellKey = OSSymbol::withCStringNoCopy("#interrupt-cells"); assert( gIODTDefaultInterruptController && gIODTNWInterruptMappingKey && gIODTAAPLInterruptsKey && gIODTPHandleKey && gIODTInterruptParentKey && gIODTPHandles && gIODTPHandleMap && gIODTInterruptCellKey ); freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry )) && (kSuccess == DTGetProperty( mapEntry, "DeviceTree", (void **) &dtMap, &propSize )) && ((2 * sizeof(uint32_t)) == propSize); parent = MakeReferenceTable( (DTEntry)dtTop, freeDT ); stack = OSArray::withObjects( (const OSObject **) &parent, 1, 10 ); DTCreateEntryIterator( (DTEntry)dtTop, &iter ); do { parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1); //parent->release(); stack->removeObject( stack->getCount() - 1); while( kSuccess == DTIterateEntries( iter, &dtChild) ) { child = MakeReferenceTable( dtChild, freeDT ); child->attachToParent( parent, gIODTPlane); AddPHandle( child ); if( kSuccess == DTEnterEntry( iter, dtChild)) { stack->setObject( parent); parent = child; } // only registry holds retain child->release(); } } while( stack->getCount() && (kSuccess == DTExitEntry( iter, &dtChild))); stack->release(); DTDisposeEntryIterator( iter); // parent is now root of the created tree // make root name first compatible entry (purely cosmetic) if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) { parent->setName( parent->getName(), gIODTPlane ); parent->setName( (const char *) prop->getBytesNoCopy() ); } // attach tree to meta root parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane); parent->release(); if( freeDT ) { // free original device tree DTInit(0); IODTFreeLoaderInfo( "DeviceTree", (void *)dtMap[0], (int) round_page(dtMap[1]) ); } // adjust tree gIODTSharedInterrupts = OSDictionary::withCapacity(4); allInts = OSDictionary::withCapacity(4); intMap = false; regIter = IORegistryIterator::iterateOver( gIODTPlane, kIORegistryIterateRecursively ); assert( regIter && allInts && gIODTSharedInterrupts ); if( regIter && allInts && gIODTSharedInterrupts ) { while( (child = regIter->getNextObject())) { IODTMapInterruptsSharing( child, allInts ); if( !intMap && child->getProperty( gIODTInterruptParentKey)) intMap = true; } regIter->release(); } #if IODTSUPPORTDEBUG parent->setProperty("allInts", allInts); parent->setProperty("sharedInts", gIODTSharedInterrupts); regIter = IORegistryIterator::iterateOver( gIODTPlane, kIORegistryIterateRecursively ); if (regIter) { while( (child = regIter->getNextObject())) { OSArray * array = OSDynamicCast(OSArray, child->getProperty( gIOInterruptSpecifiersKey )); for( UInt32 i = 0; array && (i < array->getCount()); i++) { IOOptionBits options; IOReturn ret = IODTGetInterruptOptions( child, i, &options ); if( (ret != kIOReturnSuccess) || options) IOLog("%s[%ld] %ld (%x)\n", child->getName(), i, options, ret); } } regIter->release(); } #endif allInts->release(); if( intMap) // set a key in the root to indicate we found NW interrupt mapping parent->setProperty( gIODTNWInterruptMappingKey, (OSObject *) gIODTNWInterruptMappingKey ); return( parent); }
static IORegistryEntry * MakeReferenceTable( DTEntry dtEntry, bool copy ) { IORegistryEntry *regEntry; OSDictionary *propTable; const OSSymbol *nameKey; OSData *data; const OSSymbol *sym; DTPropertyIterator dtIter; void *prop; unsigned int propSize; char *name; char location[ 32 ]; bool noLocation = true; regEntry = new IOService; if( regEntry && (false == regEntry->init())) { regEntry->release(); regEntry = 0; } if( regEntry && (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) { propTable = regEntry->getPropertyTable(); while( kSuccess == DTIterateProperties( dtIter, &name)) { if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) continue; if( copy) { nameKey = OSSymbol::withCString(name); data = OSData::withBytes(prop, propSize); } else { nameKey = OSSymbol::withCStringNoCopy(name); data = OSData::withBytesNoCopy(prop, propSize); } assert( nameKey && data ); propTable->setObject( nameKey, data); data->release(); nameKey->release(); if( nameKey == gIODTNameKey ) { if( copy) sym = OSSymbol::withCString( (const char *) prop); else sym = OSSymbol::withCStringNoCopy( (const char *) prop); regEntry->setName( sym ); sym->release(); } else if( nameKey == gIODTUnitKey ) { // all OF strings are null terminated... except this one if( propSize >= (int) sizeof(location)) propSize = sizeof(location) - 1; strncpy( location, (const char *) prop, propSize ); location[ propSize ] = 0; regEntry->setLocation( location ); propTable->removeObject( gIODTUnitKey ); noLocation = false; } else if(noLocation && (!strncmp(name, "reg", sizeof("reg")))) { // default location - override later snprintf(location, sizeof(location), "%X", *((uint32_t *) prop)); regEntry->setLocation( location ); } } DTDisposePropertyIterator( dtIter); } return( regEntry); }
void ListHookedDevice::Item::setDeviceIdentifier(void) { if (! device_) return; IORegistryEntry* dev = device_; while (dev) { const OSNumber* vid = NULL; vid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDVendorIDKey)); const OSNumber* pid = NULL; pid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDProductIDKey)); if (vid && pid) { deviceIdentifier_.setVendor(vid->unsigned32BitValue()); deviceIdentifier_.setProduct(pid->unsigned32BitValue()); goto finish; } else { // ApplePS2Keyboard does not have ProductID, // so we check for Manufacturer and Product strings const char* name = dev->getName(); if (name && strcmp(name, "ApplePS2Keyboard") == 0) { // kIOHIDManufacturerKey == "Manufacturer" // kIOHIDProductKey == "Product" const OSString* manufacturer = OSDynamicCast(OSString, dev->getProperty(kIOHIDManufacturerKey)); const OSString* product = OSDynamicCast(OSString, dev->getProperty(kIOHIDProductKey)); if (manufacturer && product) { if (manufacturer->isEqualTo("Apple") && product->isEqualTo("Keyboard")) { deviceIdentifier_.setVendor(DeviceVendor::APPLE_COMPUTER); deviceIdentifier_.setProduct(DeviceProduct::APPLE_INTERNAL_KEYBOARD_TRACKPAD_0x0218); goto finish; } } } } // check parent property. dev = dev->getParentEntry(IORegistryEntry::getPlane(kIOServicePlane)); } finish: // Set LocationID if (dev) { const OSNumber* locationid = NULL; locationid = OSDynamicCast(OSNumber, dev->getProperty(kIOHIDLocationIDKey)); if (locationid) { deviceIdentifier_.setLocation(locationid->unsigned32BitValue()); } } IOLOG_DEBUG("HookedDevice::setVendorProductLocation device_:%p, vendor:0x%04x, product:0x%04x location:0x%04x\n", device_, deviceIdentifier_.getVendor().get(), deviceIdentifier_.getProduct().get(), deviceIdentifier_.getLocation().get()); }
IOPolledFilePollers * IOPolledFilePollers::copyPollers(IOService * media) { IOPolledFilePollers * vars; IOReturn err; IOService * service; OSObject * obj; IORegistryEntry * next; IORegistryEntry * child; if ((obj = media->copyProperty(kIOPolledInterfaceStackKey))) { return (OSDynamicCast(IOPolledFilePollers, obj)); } do { vars = OSTypeAlloc(IOPolledFilePollers); vars->init(); vars->pollers = OSArray::withCapacity(4); if (!vars->pollers) { err = kIOReturnNoMemory; break; } next = vars->media = media; do { IOPolledInterface * poller; OSObject * obj; obj = next->getProperty(kIOPolledInterfaceSupportKey); if (kOSBooleanFalse == obj) { vars->pollers->flushCollection(); break; } else if ((poller = OSDynamicCast(IOPolledInterface, obj))) vars->pollers->setObject(poller); if ((service = OSDynamicCast(IOService, next)) && service->getDeviceMemory() && !vars->pollers->getCount()) break; child = next; } while ((next = child->getParentEntry(gIOServicePlane)) && child->isParent(next, gIOServicePlane, true)); if (!vars->pollers->getCount()) { err = kIOReturnUnsupported; break; } } while (false); media->setProperty(kIOPolledInterfaceStackKey, vars); return (vars); }
bool net_lundman_zfs_zvol::start (IOService *provider) { bool res = super::start(provider); IOLog("ZFS: Loading module ... \n"); sysctl_register_oid(&sysctl__zfs); sysctl_register_oid(&sysctl__zfs_kext_version); /* * Initialize /dev/zfs, this calls spa_init->dmu_init->arc_init-> etc */ zfs_ioctl_osx_init(); /* registerService() allows zconfigd to match against the service */ this->registerService(); ///sysctl_register_oid(&sysctl__debug_maczfs); //sysctl_register_oid(&sysctl__debug_maczfs_stalk); zfs_vfsops_init(); /* * When is the best time to start the system_taskq? It is strictly * speaking not used by SPL, but by ZFS. ZFS should really start it? */ system_taskq_init(); /* * hostid is left as 0 on OSX, and left to be set if developers wish to * use it. If it is 0, we will hash the hardware.uuid into a 32 bit * value and set the hostid. */ if (!zone_get_hostid(NULL)) { uint32_t myhostid = 0; IORegistryEntry *ioregroot = IORegistryEntry::getRegistryRoot(); if(ioregroot) { //IOLog("ioregroot is '%s'\n", ioregroot->getName(gIOServicePlane)); IORegistryEntry *macmodel = ioregroot->getChildEntry(gIOServicePlane); if(macmodel) { //IOLog("macmodel is '%s'\n", macmodel->getName(gIOServicePlane)); OSObject *ioplatformuuidobj; //ioplatformuuidobj = ioregroot->getProperty("IOPlatformUUID", gIOServicePlane, kIORegistryIterateRecursively); ioplatformuuidobj = macmodel->getProperty(kIOPlatformUUIDKey); if(ioplatformuuidobj) { OSString *ioplatformuuidstr = OSDynamicCast(OSString, ioplatformuuidobj); //IOLog("IOPlatformUUID is '%s'\n", ioplatformuuidstr->getCStringNoCopy()); myhostid = fnv_32a_str(ioplatformuuidstr->getCStringNoCopy(), FNV1_32A_INIT); sysctlbyname("kern.hostid", NULL, NULL, &myhostid, sizeof(myhostid)); printf("ZFS: hostid set to %08x from UUID '%s'\n", myhostid, ioplatformuuidstr->getCStringNoCopy()); } } } } disk_remove_notifier = addMatchingNotification(gIOTerminatedNotification, serviceMatching("IOMedia"), IOkit_disk_removed_callback, this, NULL, 0); return res; }