UInt32 FakeSMCKeyStore::addKeysFromDictionary(OSDictionary* dictionary) { UInt32 keysAdded = 0; if (dictionary) { 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()); keysAdded++; } OSSafeRelease(aiterator); } } key = 0; } OSSafeRelease(iterator); } } return keysAdded; }
UInt32 FakeSMCDevice::loadKeysFromNVRAM() { UInt32 count = 0; // Find driver and load keys from NVRAM if (OSDictionary *matching = serviceMatching("IODTNVRAM")) { if (IODTNVRAM *nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15))) { 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; }
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)); bzero((void*)status, sizeof(struct AppleSMCStatus)); interrupt_handler = 0; keys = OSArray::withCapacity(1); types = OSDictionary::withCapacity(0); exposedValues = OSDictionary::withCapacity(0); // 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); if (!gKeysLock) gKeysLock = IORecursiveLockAlloc(); // 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); } } // 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; } 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; 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; }
void FakeSMCDevice::applesmc_io_data_writeb(void *opaque, uint32_t addr, uint32_t val) { struct AppleSMCStatus *s = (struct AppleSMCStatus *)opaque; // IOLog("APPLESMC: DATA Write B: %#x = %#x\n", addr, val); switch(s->cmd) { case APPLESMC_READ_CMD: if(s->read_pos < 4) { s->key[s->read_pos] = val; s->status = 0x04; } else if(s->read_pos == 4) { s->data_len = val; s->status = 0x05; s->data_pos = 0; // IOLog("APPLESMC: Key = %c%c%c%c Len = %d\n", s->key[0], s->key[1], s->key[2], s->key[3], val); applesmc_fill_data(s); } s->read_pos++; break; case APPLESMC_WRITE_CMD: // IOLog("FakeSMC: attempting to write(WRITE_CMD) to io port value %x ( %c )\n", val, val); if(s->read_pos < 4) { s->key[s->read_pos] = val; s->status = 0x04; } else if(s->read_pos == 4) { s->status = 0x05; s->data_pos=0; s->data_len = val; // IOLog("FakeSMC: System Tried to write Key = %c%c%c%c Len = %d\n", s->key[0], s->key[1], s->key[2], s->key[3], val); } else if( s->data_pos < s->data_len ) { s->value[s->data_pos] = val; s->data_pos++; s->status = 0x05; if(s->data_pos == s->data_len) { s->status = 0x00; // Add or update key char name[5]; name[4] = 0; memcpy(name, s->key, 4); FakeSMCDebugLog("system writing key %s, length %d", name, s->data_len); FakeSMCKey* key = addKeyWithValue(name, 0, s->data_len, s->value); bzero(s->value, 255); if (key) saveKeyToNVRAM(key); } }; s->read_pos++; break; case APPLESMC_GET_KEY_BY_INDEX_CMD: // IOLog("FakeSMC: System Tried to write GETKEYBYINDEX = %x (%c) at pos %x\n",val , val, s->read_pos); if(s->read_pos < 4) { s->key_index += val << (24 - s->read_pos * 8); s->status = 0x04; s->read_pos++; }; if(s->read_pos == 4) { s->status = 0x05; // IOLog("FakeSMC: trying to find key by index %x\n", s->key_index); if(const char * key = applesmc_get_key_by_index(s->key_index, s)) bcopy(key, s->key, 4); } break; case APPLESMC_GET_KEY_TYPE_CMD: // IOLog("FakeSMC: System Tried to write GETKEYTYPE = %x (%c) at pos %x\n",val , val, s->read_pos); if(s->read_pos < 4) { s->key[s->read_pos] = val; s->status = 0x04; }; s->read_pos++; if(s->read_pos == 4) { s->data_len = 6; ///s->data_len = val ; ? val should be 6 here too s->status = 0x05; s->data_pos=0; applesmc_fill_info(s); } break; } }