void BatteryTracker::stop(IOService* provider) { DEBUG_LOG("BatteryTracker::stop: entering stop\n"); OSSafeReleaseNULL(m_pBatteryList); if (NULL != m_pLock) { IORecursiveLockFree(m_pLock); m_pLock = NULL; } if (m_pCmdGate) { IOWorkLoop* pWorkLoop = getWorkLoop(); if (pWorkLoop) pWorkLoop->removeEventSource(m_pCmdGate); m_pCmdGate->release(); m_pCmdGate = NULL; } IOService::stop(provider); }
void ApplePS2CypressTouchPad::stop( IOService * provider ) { // // The driver has been instructed to stop. Note that we must break all // connections to other service objects now (ie. no registered actions, // no pointers and retains to objects, etc), if any. // assert(_device == provider); // // Disable the mouse itself, so that it may stop reporting mouse events. // setTouchPadEnable(false); // // Uninstall the interrupt handler. // if ( _interruptHandlerInstalled ) _device->uninstallInterruptAction(); _interruptHandlerInstalled = false; // // Uninstall the power control handler. // if ( _powerControlHandlerInstalled ) _device->uninstallPowerControlAction(); _powerControlHandlerInstalled = false; // // Release the pointer to the provider object. // OSSafeReleaseNULL(_device); super::stop(provider); }
void FileNVRAM::stop(IOService *provider) { // OSSafeReleaseNULL(mFilePath); if (mTimer) { mTimer->cancelTimeout(); getWorkLoop()->removeEventSource(mTimer); OSSafeReleaseNULL(mTimer); } if (mCommandGate) { getWorkLoop()->removeEventSource(mCommandGate); } PMstop(); LOG(NOTICE, "Stop called, attempting to detachFromParent\n"); IORegistryEntry* root = IORegistryEntry::fromPath("/", gIODTPlane); detachFromParent(root, gIODTPlane); LOG(NOTICE, "Stop has passed the detach point.. move along now\n"); }
bool ZFSDatasetProxy::start(IOService *provider) { OSObject *property = NULL, *size = NULL; OSString *nameString = NULL; OSNumber *sizeNum = NULL; OSDictionary *deviceDict = NULL, *protocolDict = NULL; const OSSymbol *virtualSymbol = NULL, *internalSymbol = NULL; const char *cstr = NULL; char *pstring = NULL; int plen = 0; bool started = false; size = copyProperty(kZFSPoolSizeKey, gIOServicePlane, (kIORegistryIterateRecursively|kIORegistryIterateParents)); property = copyProperty(kZFSPoolNameKey, gIOServicePlane, (kIORegistryIterateRecursively|kIORegistryIterateParents)); if (!size || !property) { dprintf("couldn't get pool name or size"); goto error; } nameString = OSDynamicCast(OSString, property); if (!nameString) { dprintf("missing pool name"); goto error; } #if 0 /* Try hard to get the name string */ do { nameString = OSDynamicCast(OSString, property); if (nameString) nameString->retain(); if (!nameString) { OSSymbol *nameSymbol; nameSymbol = OSDynamicCast(OSSymbol, property); if (!nameSymbol) { dprintf("couldn't get name"); goto error; } nameString = OSString::withCString( nameSymbol->getCStringNoCopy()); } } while (0); #endif sizeNum = OSDynamicCast(OSNumber, size); if (!sizeNum) { dprintf("invalid size"); goto error; } _pool_bcount = sizeNum->unsigned64BitValue() / DEV_BSIZE; sizeNum = 0; size->release(); size = 0; cstr = nameString->getCStringNoCopy(); if (!cstr || (plen = strlen(cstr) + 1) == 1) { goto error; } pstring = (char *)IOMalloc(plen); if (!pstring) { goto error; } snprintf(pstring, plen, "%s", cstr); productString = pstring; pstring = 0; if (IOBlockStorageDevice::start(provider) == false) { dprintf("BlockStorageDevice start failed"); goto error; } started = true; deviceDict = OSDynamicCast(OSDictionary, getProperty(kIOPropertyDeviceCharacteristicsKey)); if (deviceDict) { /* Clone a new dictionary */ deviceDict = OSDictionary::withDictionary(deviceDict); if (!deviceDict) { dprintf("dict clone failed"); goto error; } } if (!deviceDict) { dprintf("creating new device dict"); deviceDict = OSDictionary::withCapacity(1); } if (!deviceDict) { dprintf("missing device dict"); goto error; } deviceDict->setObject(kIOPropertyProductNameKey, nameString); OSSafeReleaseNULL(nameString); if (setProperty(kIOPropertyDeviceCharacteristicsKey, deviceDict) == false) { dprintf("device dict setProperty failed"); goto error; } OSSafeReleaseNULL(deviceDict); protocolDict = OSDynamicCast(OSDictionary, getProperty(kIOPropertyProtocolCharacteristicsKey)); if (protocolDict) { /* Clone a new dictionary */ protocolDict = OSDictionary::withDictionary(protocolDict); if (!protocolDict) { dprintf("dict clone failed"); goto error; } } if (!protocolDict) { dprintf("creating new protocol dict"); protocolDict = OSDictionary::withCapacity(1); } if (!protocolDict) { dprintf("missing protocol dict"); goto error; } virtualSymbol = OSSymbol::withCString( kIOPropertyPhysicalInterconnectTypeVirtual); internalSymbol = OSSymbol::withCString( kIOPropertyInternalKey); if (!virtualSymbol || !internalSymbol) { dprintf("symbol alloc failed"); goto error; } protocolDict->setObject(kIOPropertyPhysicalInterconnectTypeKey, virtualSymbol); protocolDict->setObject(kIOPropertyPhysicalInterconnectLocationKey, internalSymbol); OSSafeReleaseNULL(virtualSymbol); OSSafeReleaseNULL(internalSymbol); if (setProperty(kIOPropertyProtocolCharacteristicsKey, protocolDict) == false) { dprintf("protocol dict setProperty failed"); goto error; } OSSafeReleaseNULL(protocolDict); registerService(kIOServiceAsynchronous); return (true); error: OSSafeReleaseNULL(size); OSSafeReleaseNULL(property); OSSafeReleaseNULL(deviceDict); OSSafeReleaseNULL(protocolDict); OSSafeReleaseNULL(nameString); OSSafeReleaseNULL(virtualSymbol); OSSafeReleaseNULL(internalSymbol); if (pstring) IOFree(pstring, plen); if (started) IOBlockStorageDevice::stop(provider); return (false); }
bool ACPISensors::start(IOService * provider) { ACPISensorsDebugLog("starting..."); if (!super::start(provider)) return false; if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) { ACPISensorsFatalLog("ACPI device not ready"); return false; } methods = OSArray::withCapacity(0); // Try to load configuration provided by ACPI device OSObject *object = NULL; // Use Kelvins? if (kIOReturnSuccess == acpiDevice->evaluateObject("KLVN", &object) && object) { if (OSNumber *kelvins = OSDynamicCast(OSNumber, object)) { useKelvins = kelvins->unsigned8BitValue() == 1; } OSSafeReleaseNULL(object); } // Allow the device to be completely disabled depending on Platform OSDictionary *configuration = getConfigurationNode(); if (configuration) { OSBoolean* disable = OSDynamicCast(OSBoolean, configuration->getObject("DisableDevice")); if (disable && disable->isTrue()) { return false; } } // Parse temperature table if (kIOReturnSuccess == acpiDevice->evaluateObject("TEMP", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryTemperature); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("temprerature description table (TEMP) not found"); // Parse voltage table if (kIOReturnSuccess == acpiDevice->evaluateObject("VOLT", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryVoltage); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("voltage description table (VOLT) not found"); // Parse amperage table if (kIOReturnSuccess == acpiDevice->evaluateObject("AMPR", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryCurrent); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("amperage description table (AMPR) not found"); // Parse power table if (kIOReturnSuccess == acpiDevice->evaluateObject("POWR", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryPower); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("power description table (POWR) not found"); // Parse tachometer table if (kIOReturnSuccess == acpiDevice->evaluateObject("TACH", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryFan); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("tachometer description table (TACH) not found"); // If nothing was found on ACPI device try to load configuration from info.plist if (object == NULL && configuration) { if (OSDictionary *temperatures = OSDynamicCast(OSDictionary, configuration->getObject("Temperatures"))) { if (OSBoolean *kelvins = OSDynamicCast(OSBoolean, temperatures->getObject("UseKelvins"))) { useKelvins = kelvins->isTrue(); } addSensorsFromDictionary(OSDynamicCast(OSDictionary, temperatures), kFakeSMCCategoryTemperature); } addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Voltages")), kFakeSMCCategoryVoltage); addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Currents")), kFakeSMCCategoryCurrent); addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Powers")), kFakeSMCCategoryPower); addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Tachometers")), kFakeSMCCategoryFan); } if (methods->getCount()) ACPISensorsInfoLog("%d sensor%s added", methods->getCount(), methods->getCount() > 1 ? "s" : ""); registerService(); ACPISensorsInfoLog("started"); return true; }
bool SuperIOPlugin::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsFatalLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *modelString = OSString::withCString(modelName); if (OSDictionary *configuration = getConfigurationNode(modelString)) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); } else HWSensorsWarningLog("no platform profile provided"); OSSafeReleaseNULL(modelString); registerService(); HWSensorsInfoLog("started"); return true; }
bool LPCSensors::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsFatalLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *modelString = OSString::withCString(modelName); if (OSDictionary *configuration = getConfigurationNode(modelString)) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); } else HWSensorsWarningLog("no platform profile provided"); OSSafeReleaseNULL(modelString); // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &LPCSensors::woorkloopTimerEvent)))) { HWSensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { HWSensorsFatalLog("failed to add timer event source into workloop"); return false; } // two power states - off and on static const IOPMPowerState powerStates[2] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; // register interest in power state changes PMinit(); provider->joinPMtree(this); registerPowerDriver(this, (IOPMPowerState *)powerStates, 2); registerService(); HWSensorsInfoLog("started"); return true; }
void BrcmPatchRAM::stop(IOService* provider) { #ifdef DEBUG uint64_t stop_time, nano_secs; clock_get_uptime(&stop_time); absolutetime_to_nanoseconds(stop_time - wake_time, &nano_secs); uint64_t milli_secs = nano_secs / 1000000; AlwaysLog("Time since wake %llu.%llu seconds.\n", milli_secs / 1000, milli_secs % 1000); #endif DebugLog("stop\n"); #if 0 #ifndef TARGET_ELCAPITAN //REVIEW: so kext can be unloaded with kextunload -p // unload native bluetooth driver IOReturn result = gIOCatalogue->terminateDriversForModule(brcmBundleIdentifier, false); if (result != kIOReturnSuccess) AlwaysLog("[%04x:%04x]: failure terminating native Broadcom bluetooth (%08x)\n", mVendorId, mProductId, result); else DebugLog("[%04x:%04x]: success terminating native Broadcom bluetooth\n", mVendorId, mProductId); // unpublish native bluetooth personality removePersonality(); #endif #endif mStopping = true; // allow firmware load already started to finish IOLockLock(mLoadFirmwareLock); OSSafeReleaseNULL(mFirmwareStore); IOWorkLoop* workLoop = getWorkLoop(); if (workLoop) { if (mTimer) { mTimer->cancelTimeout(); workLoop->removeEventSource(mTimer); mTimer->release(); mTimer = NULL; } if (mWorkSource) { workLoop->removeEventSource(mWorkSource); mWorkSource->release(); mWorkSource = NULL; mWorkPending = 0; } } PMstop(); if (mCompletionLock) { IOLockFree(mCompletionLock); mCompletionLock = NULL; } #ifndef NON_RESIDENT if (mWorkLock) { IOLockFree(mWorkLock); mWorkLock = NULL; } IOLockUnlock(mLoadFirmwareLock); #endif // #ifndef NON_RESIDENT mDevice.setDevice(NULL); mStopping = false; super::stop(provider); }
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; }
void ApplePS2Mouse::stop(IOService * provider) { // // The driver has been instructed to stop. Note that we must break all // connections to other service objects now (ie. no registered actions, // no pointers and retains to objects, etc), if any. // assert(_device == provider); // // Disable the mouse itself, so that it may stop reporting mouse events. // setMouseEnable(false); // free up the command gate IOWorkLoop* pWorkLoop = getWorkLoop(); if (pWorkLoop) { if (_cmdGate) { pWorkLoop->removeEventSource(_cmdGate); _cmdGate->release(); _cmdGate = 0; } if (_buttonTimer) { pWorkLoop->removeEventSource(_buttonTimer); _buttonTimer->release(); _buttonTimer = 0; } } // // Uninstall the interrupt handler. // if ( _interruptHandlerInstalled ) _device->uninstallInterruptAction(); _interruptHandlerInstalled = false; // // Uninstall the power control handler. // if ( _powerControlHandlerInstalled ) _device->uninstallPowerControlAction(); _powerControlHandlerInstalled = false; // // Uinstall message handler. // if (_messageHandlerInstalled) { _device->uninstallMessageAction(); _messageHandlerInstalled = false; } // // Release the pointer to the provider object. // OSSafeReleaseNULL(_device);; super::stop(provider); }
void KLDBootstrap::loadKernelExternalComponents(void) { OSDictionary * extensionsDict = NULL; // must release OSCollectionIterator * keyIterator = NULL; // must release OSString * bundleID = NULL; // don't release OSKext * theKext = NULL; // don't release OSBoolean * isKernelExternalComponent = NULL; // don't release OSKextLog(/* kext */ NULL, kOSKextLogStepLevel | kOSKextLogLoadFlag, "Loading Kernel External Components."); extensionsDict = OSKext::copyKexts(); if (!extensionsDict) { return; } keyIterator = OSCollectionIterator::withCollection(extensionsDict); if (!keyIterator) { OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag, "Failed to allocate iterator for Kernel External Components."); goto finish; } while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) { const char * bundle_id = bundleID->getCStringNoCopy(); /* Skip extensions whose bundle IDs don't start with "com.apple.kec.". */ if (!bundle_id || (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) { continue; } theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID)); if (!theKext) { continue; } isKernelExternalComponent = OSDynamicCast(OSBoolean, theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey)); if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) { OSKextLog(/* kext */ NULL, kOSKextLogStepLevel | kOSKextLogLoadFlag, "Loading kernel external component %s.", bundleID->getCStringNoCopy()); OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(), /* allowDefer */ false); } } finish: OSSafeReleaseNULL(keyIterator); OSSafeReleaseNULL(extensionsDict); return; }
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; }
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; }
// We are the best match, setup driver bool ODINXHostDevice::start(IOService *provider) { LOG(V_DEBUG, "ODINXHostDevice::start called"); this->usbDevice = OSDynamicCast(IOUSBHostDevice, provider); if (!this->usbDevice) { LOG(V_ERROR, "Provider is not an IOUSBHostDevice, this is impossible!"); // Tell the kernel to try the next highest score driver return false; } const StandardUSB::ConfigurationDescriptor *activeConfiguration = nullptr; IOReturn returnCode = NULL; if (!this->usbDevice->isOpen()) { returnCode = this->usbDevice->open(this); if (returnCode != kIOReturnSuccess && returnCode != kIOReturnExclusiveAccess) { /* * Only error if return code is neither kIOReturnSuccess or kIOReturnExclusiveAccess. * If we got kIOReturnExclusiveAccess that means we do (not?) have exclusivity and that open has already been called. */ LOG(V_ERROR, "Error opening the USB device! Code: %04X", returnCode); return false; } LOG(V_DEBUG, "Device is not open and we failed to open it!"); } // DEBUG { LOG(V_NOTE, " Manufacturer: \"%s\"\n", ODINXHostDevice::stringDescriptorToCString(this->usbDevice->getStringDescriptor(this->usbDevice->getDeviceDescriptor()->iManufacturer))); LOG(V_NOTE, " Product: \"%s\"\n", ODINXHostDevice::stringDescriptorToCString(this->usbDevice->getStringDescriptor(this->usbDevice->getDeviceDescriptor()->iProduct))); LOG(V_NOTE, " Serial No: \"%s\"\n", ODINXHostDevice::stringDescriptorToCString(this->usbDevice->getStringDescriptor(this->usbDevice->getDeviceDescriptor()->iSerialNumber))); LOG(V_NOTE, " length: %d\n", this->usbDevice->getDeviceDescriptor()->bLength); LOG(V_NOTE, " device class: %d\n", this->usbDevice->getDeviceDescriptor()->bDeviceClass); LOG(V_NOTE, " S/N: %d\n", this->usbDevice->getDeviceDescriptor()->iSerialNumber); LOG(V_NOTE, " VID:PID: %04X:%04X\n", this->usbDevice->getDeviceDescriptor()->idVendor, this->usbDevice->getDeviceDescriptor()->idProduct); LOG(V_NOTE, " bcdDevice: %04X\n", this->usbDevice->getDeviceDescriptor()->bcdDevice); LOG(V_NOTE, " iMan:iProd:iSer: %d:%d:%d\n", this->usbDevice->getDeviceDescriptor()->iManufacturer, this->usbDevice->getDeviceDescriptor()->iProduct, this->usbDevice->getDeviceDescriptor()->iSerialNumber); LOG(V_NOTE, " nb confs: %d\n", this->usbDevice->getDeviceDescriptor()->bNumConfigurations); } if (this->usbDevice->getDeviceDescriptor()->bNumConfigurations > 0 && returnCode != kIOReturnExclusiveAccess) { for (int configIndex = 0; configIndex < this->usbDevice->getDeviceDescriptor()->bNumConfigurations; configIndex++) { // Set the configuration active, the second param disables IOKit from automaticly trying to find drivers for the new interfaces since we do it ourselves. activeConfiguration = this->usbDevice->getConfigurationDescriptor(configIndex); returnCode = this->usbDevice->setConfiguration(activeConfiguration->bConfigurationValue, false); if (returnCode != kIOReturnSuccess) { LOG(V_ERROR, "Error setting the device to the configuration at index zero!"); } // Find the interfaces OSIterator *deviceInterfaceIterator = this->usbDevice->getChildIterator(gIOServicePlane); if (!deviceInterfaceIterator) { LOG(V_ERROR, "USB Device has no interfaces?!?!"); return false; } OSObject *entry = nullptr; while ((entry = deviceInterfaceIterator->getNextObject()) != nullptr) { IOUSBHostInterface *usbInterface = OSDynamicCast(IOUSBHostInterface, entry); if (!usbInterface) { LOG(V_DEBUG, "Object in interface iterator that isn't a IOUSBHostInterface!"); continue; } uint8_t interfaceClass = usbInterface->getInterfaceDescriptor()->bInterfaceClass; if (interfaceClass != USB_INTERFACE_CLASS_CDC_DATA) { LOG(V_DEBUG, "Interface isn't of the CDC Data class. Interface class: 0x%02X!", interfaceClass); continue; } { LOG(V_NOTE, "config[%d].interface[%d]: num endpoints = %d", configIndex, usbInterface->getInterfaceDescriptor()->bInterfaceNumber, usbInterface->getInterfaceDescriptor()->bNumEndpoints); LOG(V_NOTE, " Class.SubClass.Protocol: %02X.%02X.%02X", usbInterface->getInterfaceDescriptor()->bInterfaceClass, usbInterface->getInterfaceDescriptor()->bInterfaceSubClass, usbInterface->getInterfaceDescriptor()->bInterfaceProtocol); } const StandardUSB::EndpointDescriptor *endpoint = nullptr; while ((endpoint = StandardUSB::getNextEndpointDescriptor(activeConfiguration, usbInterface->getInterfaceDescriptor(), endpoint)) != nullptr) { { LOG(V_NOTE, " endpoint address: %02X\n", endpoint->bEndpointAddress); LOG(V_NOTE, " max packet size: %04X\n", endpoint->wMaxPacketSize); LOG(V_NOTE, " polling interval: %02X\n", endpoint->bInterval); } if (!inPipe || !outPipe) { if (StandardUSB::getEndpointDirection(endpoint)) { if (inPipe) { OSSafeReleaseNULL(inPipe); } this->inPipe = usbInterface->copyPipe(endpoint->bEndpointAddress); LOG(V_DEBUG, "Found an input endpoint: 0x%02X!", endpoint->bEndpointAddress); } else { if (outPipe) { OSSafeReleaseNULL(outPipe); } this->outPipe = usbInterface->copyPipe(endpoint->bEndpointAddress); LOG(V_DEBUG, "Found an output endpoint: 0x%02X!", endpoint->bEndpointAddress); } } } } OSSafeReleaseNULL(deviceInterfaceIterator); } if (!inPipe || !outPipe) { LOG(V_ERROR, "Error opening I/O pipes!"); OSSafeReleaseNULL(inPipe); OSSafeReleaseNULL(outPipe); return false; } } else if (returnCode != kIOReturnExclusiveAccess) { LOG(V_ERROR, "The USB device somehow has no valid configurations?!?!"); return false; } // Retain the device usbDevice->retain(); // Kick off input inPipe->io(inbuf.mdp, PAGE_SIZE, &inbuf.comp); this->handshake(); LOG(V_NOTE, "ODIN Mode device successfully started!"); return true; }
void ODINXHostDevice::free() { OSSafeReleaseNULL(inbuf.mdp); OSSafeReleaseNULL(outbuf.mdp); IOUSBHostDevice::free(); }
bool setOemProperties(IOService *provider) { SMBEntryPoint* eps = 0; IOMemoryDescriptor* dmiMemory = 0; IOItemCount dmiStructureCount = 0; UInt8* biosAddress = NULL; IOMemoryDescriptor * biosMemory = 0; IOMemoryMap * biosMap = 0; biosMemory = IOMemoryDescriptor::withPhysicalAddress( 0xf0000,0xfffff-0xf0000+1,kIODirectionOutIn); if(biosMemory) { biosMap = biosMemory->map(); if(biosMap) { biosAddress = (UInt8 *) biosMap->getVirtualAddress(); } } // Search 0x0f0000 - 0x0fffff for SMBIOS Ptr if(biosAddress) for (UInt32 Address = 0; Address < biosMap->getLength(); Address += 0x10) { if (*(UInt32 *)(biosAddress + Address) == SMBIOS_PTR) { eps = (SMBEntryPoint *)(biosAddress + Address); continue; } } if(eps) if (memcmp(eps->anchor, "_SM_", 4) == 0) { UInt8 csum; csum = checksum8(eps, sizeof(SMBEntryPoint)); /*HWSensorsDebugLog("DMI checksum = 0x%x", csum); HWSensorsDebugLog("DMI tableLength = %d", eps->dmi.tableLength); HWSensorsDebugLog("DMI tableAddress = 0x%x", (uint32_t) eps->dmi.tableAddress); HWSensorsDebugLog("DMI structureCount = %d", eps->dmi.structureCount); HWSensorsDebugLog("DMI bcdRevision = %x", eps->dmi.bcdRevision);*/ if (csum == 0 && eps->dmi.tableLength && eps->dmi.structureCount) { dmiStructureCount = eps->dmi.structureCount; dmiMemory = IOMemoryDescriptor::withPhysicalAddress( eps->dmi.tableAddress, eps->dmi.tableLength, kIODirectionOutIn ); } /*else { HWSensorsDebugLog("no DMI structure found"); }*/ } if (biosMap) OSSafeReleaseNULL(biosMap); if(biosMemory) OSSafeReleaseNULL(biosMemory); if ( dmiMemory ) { if (IOMemoryMap *fDMIMemoryMap = dmiMemory->map()) { decodeSMBIOSTable(provider, (void *) fDMIMemoryMap->getVirtualAddress(), fDMIMemoryMap->getLength(), dmiStructureCount ); OSSafeReleaseNULL(fDMIMemoryMap); } OSSafeReleaseNULL(dmiMemory); } return true; }
bool IOHIDInterface::start( IOService * provider ) { OSNumber * number; if ( !super::start(provider) ) return false; _owner = OSDynamicCast( IOHIDDevice, provider ); if ( !_owner ) return false; _transportString = (OSString*)copyProperty(kIOHIDTransportKey); _manufacturerString = (OSString*)copyProperty(kIOHIDManufacturerKey); _productString = (OSString*)copyProperty(kIOHIDProductKey); _serialNumberString = (OSString*)copyProperty(kIOHIDSerialNumberKey); if (_transportString && !OSDynamicCast(OSString, _transportString)) OSSafeReleaseNULL(_transportString); if (_manufacturerString && !OSDynamicCast(OSString, _manufacturerString)) OSSafeReleaseNULL(_manufacturerString); if (_productString && !OSDynamicCast(OSString, _productString)) OSSafeReleaseNULL(_productString); if (_serialNumberString && !OSDynamicCast(OSString, _serialNumberString)) OSSafeReleaseNULL(_serialNumberString); number = (OSNumber*)copyProperty(kIOHIDLocationIDKey); if ( OSDynamicCast(OSNumber, number) ) _locationID = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)copyProperty(kIOHIDVendorIDKey); if ( OSDynamicCast(OSNumber, number) ) _vendorID = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)copyProperty(kIOHIDVendorIDSourceKey); if ( OSDynamicCast(OSNumber, number) ) _vendorIDSource = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)copyProperty(kIOHIDProductIDKey); if ( OSDynamicCast(OSNumber, number) ) _productID = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)copyProperty(kIOHIDVersionNumberKey); if ( OSDynamicCast(OSNumber, number) ) _version = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)copyProperty(kIOHIDCountryCodeKey); if ( number ) _countryCode = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)_owner->copyProperty(kIOHIDMaxInputReportSizeKey); if ( OSDynamicCast(OSNumber, number) ) _maxReportSize[kIOHIDReportTypeInput] = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)_owner->copyProperty(kIOHIDMaxOutputReportSizeKey); if ( OSDynamicCast(OSNumber, number) ) _maxReportSize[kIOHIDReportTypeOutput] = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)_owner->copyProperty(kIOHIDMaxFeatureReportSizeKey); if ( OSDynamicCast(OSNumber, number) ) _maxReportSize[kIOHIDReportTypeFeature] = number->unsigned32BitValue(); OSSafeReleaseNULL(number); number = (OSNumber*)_owner->copyProperty(kIOHIDReportIntervalKey); if ( OSDynamicCast(OSNumber, number) ) _reportInterval = number->unsigned32BitValue(); OSSafeReleaseNULL(number); registerService(kIOServiceAsynchronous); return true; }
void FileNVRAM::timeoutOccurred(OSObject *target, IOTimerEventSource* timer) { static int retryCount; if (target) { FileNVRAM* self = OSDynamicCast(FileNVRAM, target); if (self) { uint64_t timeout = 20000; // 20ms // Check to see if BSD has been published, if so sync(); OSDictionary * dict = 0; IOService * match = 0; boolean_t found = false; do { dict = IOService::resourceMatching("IOBSD"); if (dict) { if (IOService::waitForMatchingService(dict, timeout)) { found = true; } } } while (false); OSSafeReleaseNULL(dict); OSSafeReleaseNULL(match); if (found) { UInt8 mLoggingLevel = self->mLoggingLevel; LOG(NOTICE, "BSD found, syncing\n"); // TODO: Read /Extra/NVRAM/nvram.plist and populate the device tree. char* buffer; uint64_t len; if (self->read_buffer(&buffer, &len, self->mCtx)) { retryCount++; LOG(ERROR, "Unable to read in nvram data at %s\n", self->mFilePath->getCStringNoCopy()); // TODO: Check if / is mounted, and if not, try again until it is. if (retryCount < 100) { timer->setTimeoutMS(100); } else { self->mSafeToSync = true; self->registerNVRAM(); } } else { self->mSafeToSync = false; timer->cancelTimeout(); self->getWorkLoop()->removeEventSource(timer); timer->release(); self->mTimer = NULL; if (len > strlen(NVRAM_FILE_HEADER) + strlen(NVRAM_FILE_FOOTER) + 1) { char* xml = buffer + strlen(NVRAM_FILE_HEADER); size_t xmllen = (size_t)len - strlen(NVRAM_FILE_HEADER) - strlen(NVRAM_FILE_FOOTER); xml[xmllen-1] = 0; OSString *errmsg = 0; OSObject* nvram = OSUnserializeXML(xml, &errmsg); if (nvram) { OSDictionary* data = OSDynamicCast(OSDictionary, nvram); //if(data) self->setPropertyTable(data); if (data) { self->copyUnserialzedData(NULL, data); } nvram->release(); } } IOFree(buffer, (size_t)len); self->mSafeToSync = true; self->registerNVRAM(); //self->sync(); } } else { timer->setTimeoutMS(50); } } else { //printf("Self is not of type FileNVRAM.\n"); } } }
/* * Common KeyMap initialization */ bool IOHIKeyboardMapper::init( IOHIKeyboard *delegate, const UInt8 *map, UInt32 mappingLen, bool mappingShouldBeFreed ) { _mappingShouldBeFreed = mappingShouldBeFreed; _parsedMapping.mapping = map; _parsedMapping.mappingLen = mappingLen; if (!super::init()) return false; _delegate = delegate; if (!parseKeyMapping(map, mappingLen, &_parsedMapping)) return false; // _hidSystem = NULL; // _stateDirty = false; _reserved = IONew(ExpansionData, 1); bzero(_reserved, sizeof(ExpansionData)); // _ejectTimerEventSource = 0; // // _f12Eject_State = 0; // // _eject_Delay_MS = kEjectF12DelayMS; // // _slowKeys_State = 0; // // _slowKeys_Delay_MS = 0; // // _slowKeysTimerEventSource = 0; _specialKeyModifierFlags = 0; // _supportsF12Eject = 0; // _cached_KeyBits = 0; _cachedAlphaLockModDefs = 0; // If there are right hand modifiers defined, set a property if (_delegate && (_parsedMapping.maxMod > 0)) { if ( _delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) ) { _delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanTrue); _cachedAlphaLockModDefs = _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK]; } else { _delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanFalse); } UInt32 supportedModifiers = 0; OSNumber * number = 0; number = (OSNumber *)_delegate->copyProperty(kIOHIDKeyboardSupportedModifiersKey); if (number) supportedModifiers = number->unsigned32BitValue(); OSSafeReleaseNULL(number); _delegate->setProperty( kIOHIDKeyboardSupportedModifiersKey, supportedModifiers, 32 ); if ( (supportedModifiers & NX_DEVICERSHIFTKEYMASK) || (supportedModifiers & NX_DEVICERCTLKEYMASK) || (supportedModifiers & NX_DEVICERALTKEYMASK) || (supportedModifiers & NX_DEVICERCMDKEYMASK) ) { _delegate->setProperty("HIDKeyboardRightModifierSupport", kOSBooleanTrue); } } if (_parsedMapping.numDefs && _delegate) { _delegate->setProperty("HIDKeyboardKeysDefined", kOSBooleanTrue); } if ( !_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) ) { UInt32 myFlags = _delegate->deviceFlags(); if ( _delegate->alphaLock() ) { _specialKeyModifierFlags |= NX_ALPHASHIFTMASK; myFlags |= NX_ALPHASHIFTMASK; _delegate->IOHIKeyboard::setDeviceFlags(myFlags); } else { _specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK; myFlags &= ~NX_ALPHASHIFTMASK; _delegate->IOHIKeyboard::setDeviceFlags(myFlags); } } return true; }
void KLDBootstrap::readBuiltinPersonalities(void) { OSObject * parsedXML = NULL; // must release OSArray * builtinExtensions = NULL; // do not release OSArray * allPersonalities = NULL; // must release OSString * errorString = NULL; // must release kernel_section_t * infosect = NULL; // do not free OSCollectionIterator * personalitiesIterator = NULL; // must release unsigned int count, i; OSKextLog(/* kext */ NULL, kOSKextLogStepLevel | kOSKextLogLoadFlag, "Reading built-in kernel personalities for I/O Kit drivers."); /* Look in the __BUILTIN __info segment for an array of Info.plist * entries. For each one, extract the personalities dictionary, add * it to our array, then push them all (without matching) to * the IOCatalogue. This can be used to augment the personalities * in gIOKernelConfigTables, especially when linking entire kexts into * the mach_kernel image. */ infosect = getsectbyname("__BUILTIN", "__info"); if (!infosect) { // this isn't fatal goto finish; } parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr, &errorString); if (parsedXML) { builtinExtensions = OSDynamicCast(OSArray, parsedXML); } if (!builtinExtensions) { const char * errorCString = "(unknown error)"; if (errorString && errorString->getCStringNoCopy()) { errorCString = errorString->getCStringNoCopy(); } else if (parsedXML) { errorCString = "not an array"; } OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogLoadFlag, "Error unserializing built-in personalities: %s.", errorCString); goto finish; } // estimate 3 personalities per Info.plist/kext count = builtinExtensions->getCount(); allPersonalities = OSArray::withCapacity(count * 3); for (i = 0; i < count; i++) { OSDictionary * infoDict = NULL; // do not release OSString * moduleName = NULL; // do not release OSDictionary * personalities; // do not release OSString * personalityName; // do not release OSSafeReleaseNULL(personalitiesIterator); infoDict = OSDynamicCast(OSDictionary, builtinExtensions->getObject(i)); if (!infoDict) { continue; } moduleName = OSDynamicCast(OSString, infoDict->getObject(kCFBundleIdentifierKey)); if (!moduleName) { continue; } OSKextLog(/* kext */ NULL, kOSKextLogStepLevel | kOSKextLogLoadFlag, "Adding personalities for built-in driver %s:", moduleName->getCStringNoCopy()); personalities = OSDynamicCast(OSDictionary, infoDict->getObject("IOKitPersonalities")); if (!personalities) { continue; } personalitiesIterator = OSCollectionIterator::withCollection(personalities); if (!personalitiesIterator) { continue; // xxx - well really, what can we do? should we panic? } while ((personalityName = OSDynamicCast(OSString, personalitiesIterator->getNextObject()))) { OSDictionary * personality = OSDynamicCast(OSDictionary, personalities->getObject(personalityName)); OSKextLog(/* kext */ NULL, kOSKextLogDetailLevel | kOSKextLogLoadFlag, "Adding built-in driver personality %s.", personalityName->getCStringNoCopy()); if (personality && !personality->getObject(kCFBundleIdentifierKey)) { personality->setObject(kCFBundleIdentifierKey, moduleName); } allPersonalities->setObject(personality); } } gIOCatalogue->addDrivers(allPersonalities, false); finish: OSSafeReleaseNULL(parsedXML); OSSafeReleaseNULL(allPersonalities); OSSafeReleaseNULL(errorString); OSSafeReleaseNULL(personalitiesIterator); return; }
bool IOHIDLibUserClient::start(IOService *provider) { OSDictionary *matching = NULL; if (!super::start(provider)) return false; fNub = OSDynamicCast(IOHIDDevice, provider); if (!fNub) return false; fWL = getWorkLoop(); if (!fWL) return false; fWL->retain(); OSNumber *primaryUsage = (OSNumber*)fNub->copyProperty(kIOHIDPrimaryUsageKey); OSNumber *primaryUsagePage = (OSNumber*)fNub->copyProperty(kIOHIDPrimaryUsagePageKey); if ((OSDynamicCast(OSNumber, primaryUsagePage) && (primaryUsagePage->unsigned32BitValue() == kHIDPage_GenericDesktop)) && (OSDynamicCast(OSNumber, primaryUsage) && ((primaryUsage->unsigned32BitValue() == kHIDUsage_GD_Keyboard) || (primaryUsage->unsigned32BitValue() == kHIDUsage_GD_Keypad)))) { fNubIsKeyboard = true; } OSSafeReleaseNULL(primaryUsage); OSSafeReleaseNULL(primaryUsagePage); IOCommandGate * cmdGate = IOCommandGate::commandGate(this); if (!cmdGate) goto ABORT_START; fWL->addEventSource(cmdGate); fGate = cmdGate; fResourceES = IOInterruptEventSource::interruptEventSource (this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &IOHIDLibUserClient::resourceNotificationGated)); if ( !fResourceES ) goto ABORT_START; fWL->addEventSource(fResourceES); // Get notified everytime Root properties change matching = serviceMatching("IOResources"); fResourceNotification = addMatchingNotification( gIOPublishNotification, matching, OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &IOHIDLibUserClient::resourceNotification), this); matching->release(); matching = NULL; if ( !fResourceNotification ) goto ABORT_START; return true; ABORT_START: if (fResourceES) { fWL->removeEventSource(fResourceES); fResourceES->release(); fResourceES = 0; } if (fGate) { fWL->removeEventSource(fGate); fGate->release(); fGate = 0; } fWL->release(); fWL = 0; return false; }