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 FakeSMCPlugin::free() { HWSensorsDebugLog("[free] freenig sensors collection"); OSSafeRelease(sensors); super::free(); }
bool ApplePS2Mouse::init(OSDictionary * dict) { // // Initialize this object's minimal state. This is invoked right after this // object is instantiated. // if (!super::init(dict)) return false; // find config specific to Platform Profile OSDictionary* list = OSDynamicCast(OSDictionary, dict->getObject(kPlatformProfile)); OSDictionary* config = ApplePS2Controller::makeConfigurationNode(list); if (config) { // if DisableDevice is Yes, then do not load at all... OSBoolean* disable = OSDynamicCast(OSBoolean, config->getObject(kDisableDevice)); if (disable && disable->isTrue()) { config->release(); return false; } #ifdef DEBUG // save configuration for later/diagnostics... setProperty(kMergedConfiguration, config); #endif } // initialize state... _device = 0; _interruptHandlerInstalled = false; _packetByteCount = 0; _lastdata = 0; _packetLength = kPacketLengthStandard; defres = 150 << 16; // (default is 150 dpi; 6 counts/mm) forceres = false; mouseyinverter = 1; // 1 for normal, -1 for inverting scrollyinverter = 1; // 1 for normal, -1 for inverting _type = kMouseTypeStandard; _buttonCount = 3; _mouseInfoBytes = (UInt32)-1; ignoreall = false; ledpresent = false; resmode = -1; forcesetres = false; scrollres = 10; actliketrackpad = false; keytime = 0; maxaftertyping = 500000000; buttonmask = ~0; scroll = true; noled = false; wakedelay = 1000; usb_mouse_stops_trackpad = true; mousecount = 0; _cmdGate = 0; // state for middle button _buttonTimer = 0; _mbuttonstate = STATE_NOBUTTONS; _pendingbuttons = 0; _buttontime = 0; _maxmiddleclicktime = 100000000; // load settings setParamPropertiesGated(config); OSSafeRelease(config); // remove some properties so system doesn't think it is a trackpad // this should cause "Product" = "Mouse" in ioreg. if (!actliketrackpad) { removeProperty("VendorID"); removeProperty("ProductID"); removeProperty("HIDPointerAccelerationType"); removeProperty("HIDScrollAccelerationType"); removeProperty("TrackpadScroll"); } IOLog("VoodooPS2Mouse Version 1.8.10 loaded...\n"); return true; }
void ACPIProbeProfile::free() { OSSafeRelease(this->methods); OSObject::free(); }
/****************************************************************************** * CodecCommander::start - start kernel extension and init PM ******************************************************************************/ bool CodecCommander::start(IOService *provider) { IOLog("CodecCommander: Version 2.2.1 starting.\n"); if (!provider || !super::start(provider)) { DEBUG_LOG("CodecCommander: Error loading kernel extension.\n"); return false; } // Retrieve HDEF device from IORegistry IORegistryEntry *hdaDeviceEntry = IORegistryEntry::fromPath(mConfiguration->getHDADevicePath()); if (hdaDeviceEntry != NULL) { mIntelHDA = new IntelHDA(hdaDeviceEntry, PIO, mConfiguration->getCodecNumber()); OSSafeRelease(hdaDeviceEntry); } else { DEBUG_LOG("CodecCommander: Device \"%s\" is unreachable, start aborted.\n", mConfiguration->getHDADevicePath()); return false; } if (mConfiguration->getUpdateNodes()) { IOSleep(mConfiguration->getSendDelay()); // need to wait a bit until codec can actually respond to immediate verbs int k = 0; // array index // Fetch Pin Capabilities from the range of nodes DEBUG_LOG("CodecCommander: Getting EAPD supported node list (limited to %d)\n", MAX_EAPD_NODES); for (int nodeId = mIntelHDA->getStartingNode(); nodeId <= mIntelHDA->getTotalNodes(); nodeId++) { UInt32 response = mIntelHDA->sendCommand(nodeId, HDA_VERB_GET_PARAM, HDA_PARM_PINCAP); if (response == -1) { DEBUG_LOG("CodecCommander: Failed to retrieve pin capabilities for node 0x%02x.\n", nodeId); continue; } // if bit 16 is set in pincap - node supports EAPD if (HDA_PINCAP_IS_EAPD_CAPABLE(response)) { eapdCapableNodes[k] = nodeId; k++; IOLog("CodecCommander: NID=0x%02x supports EAPD, will update state after sleep\n", nodeId); } } /* IOLog("CodecCommander:: Set 0x0A result: 0x%08x\n", mIntelHDA->sendCommand(0x0A, HDA_VERB_SET_AMP_GAIN, HDA_PARM_AMP_GAIN_SET(0x80, 0, 1, 1, 1, 0, 1))); IOLog("CodecCommander:: Set 0x0B result: 0x%08x\n", mIntelHDA->sendCommand(0x0B, HDA_VERB_SET_AMP_GAIN, HDA_PARM_AMP_GAIN_SET(0x80, 0, 1, 1, 1, 0, 1))); IOLog("CodecCommander:: Set 0x0C result: 0x%08x\n", mIntelHDA->sendCommand(0x0C, HDA_VERB_SET_AMP_GAIN, HDA_PARM_AMP_GAIN_SET(0x80, 0, 1, 1, 1, 0, 1))); for (int nodeId = mIntelHDA->getStartingNode(); nodeId <= mIntelHDA->getTotalNodes(); nodeId++) { UInt16 payload = HDA_PARM_AMP_GAIN_GET(0, 1, 1);//AC_AMP_GET_OUTPUT | AC_AMP_GET_LEFT; UInt32 response = mIntelHDA->sendCommand(nodeId, HDA_VERB_GET_AMP_GAIN, payload); if (response == -1) { DEBUG_LOG("Failed to retrieve amp gain settings for node 0x%02x.\n", nodeId); continue; } IOLog("CodecCommander:: [Amp Gain] Node: 0x%04x, Response: 0x%08x\n", nodeId, response); } */ } // Execute any custom commands registered for initialization handleStateChange(kStateInit); // notify about extra feature requests if (mConfiguration->getCheckInfinite()) DEBUG_LOG("CodecCommander: Infinite workloop requested, will start now!\n"); // init power state management & set state as PowerOn PMinit(); registerPowerDriver(this, powerStateArray, kPowerStateCount); provider->joinPMtree(this); // setup workloop and timer mWorkLoop = IOWorkLoop::workLoop(); mTimer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &CodecCommander::onTimerAction)); if (!mWorkLoop || !mTimer) stop(provider);; if (mWorkLoop->addEventSource(mTimer) != kIOReturnSuccess) stop(provider); this->registerService(0); return true; }
void ACPIProbe::free() { OSSafeRelease(profiles); OSSafeRelease(profileList); super::free(); }
bool ACPIProbe::start(IOService * provider) { ACPISensorsDebugLog("starting..."); if (!super::start(provider)) return false; if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) { ACPISensorsFatalLog("ACPI device not ready"); return false; } profiles = OSDictionary::withCapacity(0); profileList = OSArray::withCapacity(0); OSObject *object = NULL; // Try to load configuration provided by ACPI device if (kIOReturnSuccess == acpiDevice->evaluateObject("LIST", &object) && object) { if (OSArray *list = OSDynamicCast(OSArray, object)) { for (unsigned int i = 0; i < list->getCount(); i++) { if (OSString *method = OSDynamicCast(OSString, list->getObject(i))) { if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) { if (OSArray *config = OSDynamicCast(OSArray, object)) { if (config->getCount() > 4) { OSString *pName = OSDynamicCast(OSString, config->getObject(0)); OSNumber *pInterval = OSDynamicCast(OSNumber, config->getObject(1)); OSNumber *pTimeout = OSDynamicCast(OSNumber, config->getObject(2)); OSNumber *pVerbose = OSDynamicCast(OSNumber, config->getObject(3)); OSArray *pMethods = OSArray::withCapacity(config->getCount() - 4); for (unsigned int offset = 4; offset < config->getCount(); offset++) { if (OSString *methodName = OSDynamicCast(OSString, config->getObject(offset))) { pMethods->setObject(methodName); } } addProfile(pName, pMethods, pInterval, pTimeout, pVerbose); } } OSSafeRelease(object); } } } OSSafeRelease(list); } } else { ACPISensorsErrorLog("profile definition table (LIST) not found"); } // Try to load configuration from info.plist if (profiles->getCount() == 0) { if (OSDictionary *configuration = getConfigurationNode()) { OSString *pName = OSDynamicCast(OSString, configuration->getObject("ProfileName")); OSNumber *pInterval = OSDynamicCast(OSNumber, configuration->getObject("PollingInterval")); OSNumber *pTimeout = OSDynamicCast(OSNumber, configuration->getObject("PollingTimeout")); OSBoolean *pVerboseBool = OSDynamicCast(OSBoolean, configuration->getObject("VerboseLog")); OSNumber *pVerbose = OSNumber::withNumber(pVerboseBool->getValue() ? 1 : 0, 8); OSArray *pMethods = OSDynamicCast(OSArray, configuration->getObject("MethodsToPoll")); addProfile(pName, pMethods, pInterval, pTimeout, pVerbose); } } if (this->profiles->getCount()) { // Parse active profile if (kIOReturnSuccess == acpiDevice->evaluateObject("ACTV", &object) && object) { if (OSString *method = OSDynamicCast(OSString, object)) { if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) { if (OSArray *config = OSDynamicCast(OSArray, object)) { if (config->getCount() > 4) { if (OSString *profile = OSDynamicCast(OSString, config->getObject(0))) { if (!(activeProfile = (ACPIProbeProfile *)profiles->getObject(profile))) { activeProfile = (ACPIProbeProfile *)profileList->getObject(0); } } } } OSSafeRelease(object); } OSSafeRelease(method); } } // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ACPIProbe::woorkloopTimerEvent)))) { ACPISensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { ACPISensorsFatalLog("failed to add timer event source into workloop"); return false; } timerEventSource->setTimeoutMS(100); //ACPISensorsInfoLog("%d method%s registered", methods->getCount(), methods->getCount() > 1 ? "s" : ""); } // 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(); ACPISensorsInfoLog("started"); return true; }
IOReturn FakeSMCDevice::callPlatformFunction(const OSSymbol *functionName, bool waitForFunction, void *param1, void *param2, void *param3, void *param4 ) { IOReturn result = kIOReturnUnsupported; if (functionName->isEqualTo(kFakeSMCAddKeyHandler)) { result = kIOReturnBadArgument; if (param1 && param2 && param3 && param4) { const char *name = (const char *)param1; const char *type = (const char *)param2; UInt8 size = (UInt64)param3; IOService *handler = (IOService*)param4; if (name && type && size > 0 && handler) { if (addKeyWithHandler(name, type, size, handler)) result = kIOReturnSuccess; else result = kIOReturnError; } } } else if (functionName->isEqualTo(kFakeSMCGetKeyHandler)) { result = kIOReturnBadArgument; if (const char *name = (const char *)param1) { result = kIOReturnError; if (FakeSMCKey *key = OSDynamicCast(FakeSMCKey, getKey(name))) { result = kIOReturnSuccess; if (key->getHandler()) { result = kIOReturnBadArgument; if (param2) { IOService **handler = (IOService**)param2; *handler = key->getHandler(); result = kIOReturnSuccess; } } } } } else if (functionName->isEqualTo(kFakeSMCRemoveKeyHandler)) { result = kIOReturnBadArgument; if (param1) { result = kIOReturnError; if (OSCollectionIterator *iterator = OSCollectionIterator::withCollection(keys)) { IOService *handler = (IOService *)param1; while (FakeSMCKey *key = OSDynamicCast(FakeSMCKey, iterator->getNextObject())) { if (key->getHandler() == handler) key->setHandler(NULL); } result = kIOReturnSuccess; OSSafeRelease(iterator); } } } else if (functionName->isEqualTo(kFakeSMCAddKeyValue)) { result = kIOReturnBadArgument; if (param1 && param2 && param3) { const char *name = (const char *)param1; const char *type = (const char *)param2; UInt8 size = (UInt64)param3; const void *value = (const void *)param4; if (name && type && size > 0) { if (addKeyWithValue(name, type, size, value)) result = kIOReturnSuccess; else result = kIOReturnError; } } } else if (functionName->isEqualTo(kFakeSMCSetKeyValue)) { result = kIOReturnBadArgument; if (param1 && param2 && param3) { const char *name = (const char *)param1; UInt8 size = (UInt64)param2; const void *data = (const void *)param3; result = kIOReturnError; if (name && data && size > 0) { if (FakeSMCKey *key = OSDynamicCast(FakeSMCKey, getKey(name))) { if (key->setValueFromBuffer(data, size)) { result = kIOReturnSuccess; } } } } } else if (functionName->isEqualTo(kFakeSMCGetKeyValue)) { result = kIOReturnBadArgument; if (const char *name = (const char *)param1) { result = kIOReturnError; if (FakeSMCKey *key = getKey(name)) { result = kIOReturnBadArgument; if (param2 && param3) { UInt8 *size = (UInt8*)param2; const void **value = (const void **)param3; *size = key->getSize(); *value = key->getValue(); result = kIOReturnSuccess; } } } } else if (functionName->isEqualTo(kFakeSMCTakeVacantGPUIndex)) { result = kIOReturnBadArgument; KEYSLOCK; if (SInt8 *index = (SInt8*)param1) { for (UInt8 i = 0; i <= 0xf; i++) { if (!bit_get(vacantGPUIndex, BIT(i))) { bit_set(vacantGPUIndex, BIT(i)); *index = i; result = kIOReturnSuccess; break; } } if (result != kIOReturnSuccess) result = kIOReturnError; } KEYSUNLOCK; } else if (functionName->isEqualTo(kFakeSMCTakeGPUIndex)) { result = kIOReturnBadArgument; KEYSLOCK; if (UInt8 *index = (UInt8*)param1) { if (*index < 0xf && !bit_get(vacantGPUIndex, BIT(*index))) { bit_set(vacantGPUIndex, BIT(*index)); result = kIOReturnSuccess; } if (result != kIOReturnSuccess) result = kIOReturnError; } KEYSUNLOCK; } else if (functionName->isEqualTo(kFakeSMCReleaseGPUIndex)) { result = kIOReturnBadArgument; KEYSLOCK; if (UInt8 *index = (UInt8*)param1) { if (*index <= 0xf) { bit_clear(vacantGPUIndex, BIT(*index)); result = kIOReturnSuccess; } } KEYSUNLOCK; } else if (functionName->isEqualTo(kFakeSMCTakeVacantFanIndex)) { result = kIOReturnBadArgument; KEYSLOCK; if (SInt8 *index = (SInt8*)param1) { for (UInt8 i = 0; i <= 0xf; i++) { if (!bit_get(vacantFanIndex, BIT(i))) { bit_set(vacantFanIndex, BIT(i)); *index = i; updateFanCounterKey(); result = kIOReturnSuccess; break; } } if (result != kIOReturnSuccess) result = kIOReturnError; } KEYSUNLOCK; } else if (functionName->isEqualTo(kFakeSMCReleaseFanIndex)) { result = kIOReturnBadArgument; KEYSLOCK; if (UInt8 *index = (UInt8*)param1) { if (*index <= 0xf) { bit_clear(vacantFanIndex, BIT(*index)); updateFanCounterKey(); result = kIOReturnSuccess; } } KEYSUNLOCK; } else { result = super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4); } return result; }
bool FakeSMCDevice::initAndStart(IOService *platform, IOService *provider) { if (!provider || !super::init(platform, 0, 0)) return false; OSDictionary *properties = OSDynamicCast(OSDictionary, provider->getProperty("Configuration")); if (!properties) return false; status = (ApleSMCStatus *) IOMalloc(sizeof(struct AppleSMCStatus)); if (!status) return false; bzero((void*)status, sizeof(struct AppleSMCStatus)); interrupt_handler = 0; keys = OSArray::withCapacity(64); types = OSDictionary::withCapacity(16); exposedValues = OSDictionary::withCapacity(16); // Add fist key - counter key keyCounterKey = FakeSMCKey::withValue(KEY_COUNTER, TYPE_UI32, TYPE_UI32_SIZE, "\0\0\0\1"); keys->setObject(keyCounterKey); fanCounterKey = FakeSMCKey::withValue(KEY_FAN_NUMBER, TYPE_UI8, TYPE_UI8_SIZE, "\0"); keys->setObject(fanCounterKey); gKeysLock = IORecursiveLockAlloc(); if (!gKeysLock) return false; #if NVRAMKEYS useNVRAM = false; #endif #if 0 #if NVRAMKEYS /* OSString *vendor = OSDynamicCast(OSString, provider->getProperty(kFakeSMCFirmwareVendor)); static const char kChameleonID[] = "Chameleon"; static const int kChameleonIDLen = sizeof(kChameleonID)-1; bool runningChameleon = vendor && 0 == strncmp(kChameleonID, vendor->getCStringNoCopy(), kChameleonIDLen); */ //REVIEW: a bit of hack for testing... int arg_value = 1; if (PE_parse_boot_argn("-fakesmc-use-nvram", &arg_value, sizeof(arg_value))) useNVRAM = true; if (PE_parse_boot_argn("-fakesmc-no-nvram", &arg_value, sizeof(arg_value))) useNVRAM = false; //PE_parse_boot_argn("-fakesmc-force-nvram", &arg_value, sizeof(arg_value)) || !runningChameleon; #endif #endif // Load preconfigured keys FakeSMCDebugLog("loading keys..."); if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Keys"))) { if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (const OSSymbol *key = (const OSSymbol *)iterator->getNextObject()) { if (OSArray *array = OSDynamicCast(OSArray, dictionary->getObject(key))) { if (OSIterator *aiterator = OSCollectionIterator::withCollection(array)) { OSString *type = OSDynamicCast(OSString, aiterator->getNextObject()); OSData *value = OSDynamicCast(OSData, aiterator->getNextObject()); if (type && value) addKeyWithValue(key->getCStringNoCopy(), type->getCStringNoCopy(), value->getLength(), value->getBytesNoCopy()); OSSafeRelease(aiterator); } } key = 0; } OSSafeRelease(iterator); } HWSensorsInfoLog("%d preconfigured key%s added", keys->getCount(), keys->getCount() == 1 ? "" : "s"); } else { HWSensorsWarningLog("no preconfigured keys found"); } // Load wellknown type names FakeSMCDebugLog("loading types..."); if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Types"))) { if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { if (OSString *value = OSDynamicCast(OSString, dictionary->getObject(key))) { types->setObject(key, value); } } OSSafeRelease(iterator); } } #if NVRAMKEYS_EXCEPTION // Load NVRAM exception keys FakeSMCDebugLog("loading NVRAM exceptions..."); exceptionKeys = NULL; if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("ExceptionKeys"))) { exceptionKeys = OSDictionary::withCapacity(dictionary->getCount()); if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { if (OSNumber *value = OSDynamicCast(OSNumber, dictionary->getObject(key))) { if (value->unsigned32BitValue()) exceptionKeys->setObject(key, value); } } OSSafeRelease(iterator); } } #endif // Set Clover platform keys if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Clover"))) { UInt32 count = 0; if (IORegistryEntry* cloverPlatformNode = fromPath("/efi/platform", gIODTPlane)) { if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (OSString *name = OSDynamicCast(OSString, iterator->getNextObject())) { if (OSData *data = OSDynamicCast(OSData, cloverPlatformNode->getProperty(name))) { if (OSArray *items = OSDynamicCast(OSArray, dictionary->getObject(name))) { OSString *key = OSDynamicCast(OSString, items->getObject(0)); OSString *type = OSDynamicCast(OSString, items->getObject(1)); if (addKeyWithValue(key->getCStringNoCopy(), type->getCStringNoCopy(), data->getLength(), data->getBytesNoCopy())) count++; } } } OSSafeRelease(iterator); } } if (count) HWSensorsInfoLog("%d key%s exported by Clover EFI", count, count == 1 ? "" : "s"); } // Start SMC device if (!super::start(platform)) return false; this->setName("SMC"); FakeSMCSetProperty("name", "APP0001"); if (OSString *compatibleKey = OSDynamicCast(OSString, properties->getObject("smc-compatible"))) FakeSMCSetProperty("compatible", (const char *)compatibleKey->getCStringNoCopy()); else FakeSMCSetProperty("compatible", "smc-napa"); if (!this->setProperty("_STA", (unsigned long long)0x0000000b, 32)) { HWSensorsErrorLog("failed to set '_STA' property"); return false; } #ifdef DEBUG if (OSBoolean *debugKey = OSDynamicCast(OSBoolean, properties->getObject("debug"))) debug = debugKey->getValue(); else debug = false; if (OSBoolean *traceKey = OSDynamicCast(OSBoolean, properties->getObject("trace"))) trace = traceKey->getValue(); else trace = false; #endif IODeviceMemory::InitElement rangeList[1]; rangeList[0].start = 0x300; rangeList[0].length = 0x20; // rangeList[1].start = 0xfef00000; // rangeList[1].length = 0x10000; if(OSArray *array = IODeviceMemory::arrayFromList(rangeList, 1)) { this->setDeviceMemory(array); OSSafeRelease(array); } else { HWSensorsFatalLog("failed to create Device memory array"); return false; } OSArray *controllers = OSArray::withCapacity(1); if(!controllers) { HWSensorsFatalLog("failed to create controllers array"); return false; } controllers->setObject((OSSymbol *)OSSymbol::withCStringNoCopy("io-apic-0")); OSArray *specifiers = OSArray::withCapacity(1); if(!specifiers) { HWSensorsFatalLog("failed to create specifiers array"); return false; } UInt64 line = 0x06; OSData *tmpData = OSData::withBytes(&line, sizeof(line)); if (!tmpData) { HWSensorsFatalLog("failed to create specifiers data"); return false; } specifiers->setObject(tmpData); this->setProperty(gIOInterruptControllersKey, controllers) && this->setProperty(gIOInterruptSpecifiersKey, specifiers); this->attachToParent(platform, gIOServicePlane); registerService(); HWSensorsInfoLog("successfully initialized"); return true; }
UInt32 FakeSMCDevice::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"); nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15)); } if (1) { //REVIEW: just to reduce diffs 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; }