Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // FileNVRAM.c
- // FileNVRAM
- //
- // Created by Chris Morton on 1/11/13.
- // Copyright (c) 2013 xZenue LLC. All rights reserved.
- //
- // This work is licensed under the
- // Creative Commons Attribution-NonCommercial 3.0 Unported License.
- // To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/3.0
- // See also: http://www.opensource.apple.com/source/xnu/xnu-2422.90.20/iokit/Kernel/IONVRAM.cpp
- // See also: http://www.opensource.apple.com/source/xnu/xnu-2050.48.11/iokit/Drivers/platform/drvAppleNVRAM/AppleNVRAM.cpp
- #include "FileNVRAM.h"
- #include <sys/proc.h>
- #include <sys/vnode.h>
- #include <sys/fcntl.h>
- #include <IOKit/IOCommandGate.h>
- #include <IOKit/storage/IOMedia.h>
- #include <string.h>
- extern void kdb_printf(const char *fmt, ...);
- #define INFO(fmt, ...) { if (_shouldLog) ERROR("func: %s, " fmt, __FUNCTION__, ##__VA_ARGS__) }
- #define ERROR(fmt, ...) {\
- char pname[256];\
- proc_name(proc_pid(vfs_context_proc(vfs_context_current())), pname, sizeof(pname));\
- IOLog("Caller: %s, line: %d, " fmt "\n", pname, __LINE__, ##__VA_ARGS__);\
- }
- #define kIOPMPowerOff 0
- #define POWER_STATE_OFF 0
- #define POWER_STATE_ON 1
- static IOPMPowerState sPowerStates[] = {
- {1, kIOPMPowerOff, kIOPMPowerOff, kIOPMPowerOff, 0, 0, 0, 0, 0, 0, 0, 0},
- {1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0}
- };
- OSDefineMetaClassAndStructors(AppleNVRAM, super);
- #pragma mark Statics
- static inline void gen_random(char *s, size_t len) {//TODO: Not all characters have the same prob
- static const char alphanum[] =
- "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- while (len)
- s[--len] = alphanum[random() % (sizeof(alphanum) - 1)];
- }
- #pragma mark IORegistryEntry
- bool AppleNVRAM::init(OSDictionary *dictionary) {
- return IOService::init(dictionary);
- }
- bool AppleNVRAM::init(IORegistryEntry *old, const IORegistryPlane *plane) {
- _shouldLog = true;
- INFO("%p, %p", old, plane);
- return IOService::init(old, plane);
- }
- OSObject *AppleNVRAM::getProperty(const OSSymbol *aKey) const {
- OSObject *value = IOService::getProperty(aKey);
- if (_shouldLog) {
- if (value) {
- OSSerialize *s = OSSerialize::withCapacity(1000);
- if (value->serialize(s))
- INFO("%s = %s", aKey->getCStringNoCopy(), s->text())
- else
- INFO("%s = %p", aKey->getCStringNoCopy(), value);
- s->release();
- }
- else
- INFO("%s = NULL", aKey->getCStringNoCopy());
- }
- return value;
- }
- OSObject *AppleNVRAM::getProperty(const char *aKey) const {
- if (const OSSymbol *keySymbol = OSSymbol::withCStringNoCopy(aKey)) {
- OSObject *theObject = getProperty(keySymbol);
- keySymbol->release();
- return theObject;
- }
- else
- return NULL;
- }
- OSObject *AppleNVRAM::copyProperty(const OSSymbol *aKey) const {
- return IORegistryEntry::copyProperty(aKey);
- }
- OSObject *AppleNVRAM::copyProperty(const char *aKey) const {
- return IORegistryEntry::copyProperty(aKey);
- }
- void AppleNVRAM::removeProperty(const OSSymbol *aKey) {
- if (IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator) == kIOReturnSuccess) {
- INFO("%p", aKey);
- IOService::removeProperty(aKey);
- _changeCount++;
- }
- }
- bool AppleNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject) {
- if (IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator) != kIOReturnSuccess)
- return false;
- if (_shouldLog) {
- OSSerialize *s = OSSerialize::withCapacity(1000);
- if (anObject->serialize(s))
- INFO("%s, (%s) %s", aKey->getCStringNoCopy(), anObject->getMetaClass()->getClassName(), s->text())
- else
- INFO("%s, (%s) %p", aKey->getCStringNoCopy(), anObject->getMetaClass()->getClassName(), anObject);
- s->release();
- }
- static const char *legacy[] = { "boot-args", "boot-script", NULL };
- int i = 0;
- anObject->retain();
- if (OSString *str = OSDynamicCast(OSString, aKey))
- while (legacy[i])
- if (str->isEqualTo(legacy[i++])) {
- INFO("Found legacy key %s", str->getCStringNoCopy());
- if (OSData *data = OSData::withData(OSDynamicCast(OSData, anObject))) {
- data->appendByte(0, 1);
- anObject->release();
- anObject = OSString::withCString((const char *)data->getBytesNoCopy());
- data->release();
- }
- break;
- }
- bool stat = IOService::setProperty(aKey, anObject);
- anObject->release();
- _changeCount++;
- return stat;
- }
- IOReturn AppleNVRAM::setProperties(OSObject *properties) {
- OSDictionary *dict;
- OSCollectionIterator *iter;
- if (!(dict = OSDynamicCast(OSDictionary, properties)) || !(iter = OSCollectionIterator::withCollection(dict)))
- return kIOReturnBadArgument;
- bool result = true, syncNow = false;
- while (result) {
- const OSSymbol *key;
- if (!(key = OSDynamicCast(OSSymbol, iter->getNextObject())))
- break;
- OSObject *object;
- if (!(object = dict->getObject(key)))
- continue;
- const OSString *tmpStr;
- if (key->isEqualTo(kIONVRAMDeletePropertyKey)) {
- if ((result = tmpStr = OSDynamicCast(OSString, object))) {
- key = OSSymbol::withString(tmpStr);
- removeProperty(key);
- key->release();
- }
- }
- else if (key->isEqualTo(kIONVRAMSyncNowPropertyKey)) {
- if ((result = OSDynamicCast(OSString, object)))
- syncNow = true;
- }
- else
- result = setProperty(key, object);
- }
- iter->release();
- if (syncNow)
- _commandGate->runCommand();
- return result ? kIOReturnSuccess : kIOReturnError;
- }
- bool AppleNVRAM::serializeProperties(OSSerialize *s) const {
- bool result = IOService::serializeProperties(s);
- INFO("%p = %s", s, s->text());
- return result;
- }
- #pragma mark IOService
- bool AppleNVRAM::start(IOService *provider) {
- _shouldLog = true;
- INFO("%d", _isReady);
- if (_isReady)
- return true;
- if (!super::start(provider))
- return false;
- INFO("%d", _isReady);
- _filePath = OSString::withCString(NVRAM_LOC_DEFAULT);
- _panic = NULL;
- if ((_commandGate = IOCommandGate::commandGate(this, _sync)))
- getWorkLoop()->addEventSource(_commandGate);
- if (OSDictionary *dict = OSDictionary::withCapacity(1)) {
- setPropertyTable(dict);
- dict->release();
- }
- else
- return false;
- IORegistryEntry *root = IORegistryEntry::fromPath("/", gIODTPlane);
- if (IORegistryEntry *bootnvram = IORegistryEntry::fromPath(NVRAM_LOC_DT, gIODTPlane)) {
- copyEntryProperties(NULL, bootnvram);
- bootnvram->detachFromParent(root, gIODTPlane);
- bootnvram->release();
- }
- if (!getProperty(NVRAM_KEY_MLB)) {
- OSString *str = OSString::withCString(NVRAM_COMMAND_MLB);
- handleSetting(str, kOSBooleanTrue);
- str->release();
- }
- if (!getProperty(NVRAM_KEY_ROM)) {
- OSString *str = OSString::withCString(NVRAM_COMMAND_ROM);
- handleSetting(str, kOSBooleanTrue);
- str->release();
- }
- _isReady = true;
- PMinit();
- registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(*sPowerStates));
- provider->joinPMtree(this);
- _context = vfs_context_create(NULL);
- _isAwake = true;
- if (OSDictionary *m = nameMatching("IOBSD")) {
- addMatchingNotification(gIOPublishNotification, m, BSDReady, this);
- m->release();
- }
- setName("AppleEFINVRAM");
- setName("options", gIODTPlane);
- attachToParent(root, gIODTPlane);
- root->release();
- registerService();
- if (const OSSymbol *funcSym = OSSymbol::withCString("RegisterNVRAM")) {
- callPlatformFunction(funcSym, false, this, NULL, NULL, NULL);
- funcSym->release();
- }
- return true;
- }
- void AppleNVRAM::stop(IOService *provider) {
- OSSafeReleaseNULL(_filePath);
- if (_commandGate) {
- getWorkLoop()->removeEventSource(_commandGate);
- OSSafeReleaseNULL(_commandGate);
- }
- OSSafeReleaseNULL(_panic);
- PMstop();
- INFO("Attempting detachFromParent");
- vfs_context_rele(_context);
- if (IORegistryEntry *root = IORegistryEntry::fromPath("/", gIODTPlane)) {
- detachFromParent(root, gIODTPlane);
- root->release();
- }
- INFO("Passed the detach point");
- }
- IOReturn AppleNVRAM::setPowerState(unsigned long whichState, IOService *whatDevice) {
- INFO("state %lu", whichState);
- switch (whichState) {
- case POWER_STATE_OFF:
- INFO("Entering sleep");
- _isAwake = false;
- break;
- case POWER_STATE_ON:
- default:
- INFO("Waking");
- _isAwake = true;
- break;
- }
- return kIOPMAckImplied;
- }
- bool AppleNVRAM::passiveMatch(OSDictionary *matching, bool changesOK) {
- OSString *str = OSDynamicCast(OSString, matching->getObject(gIOProviderClassKey));
- if (str)
- INFO("%s", str->getCStringNoCopy());
- return str && str->isEqualTo("AppleEFINVRAM") ?: super::passiveMatch(matching, changesOK);
- }
- void AppleNVRAM::systemWillShutdown(IOOptionBits specifier) {
- INFO("");
- _commandGate->runCommand();
- super::systemWillShutdown(specifier);
- }
- #pragma mark IODTNVRAM
- void AppleNVRAM::sync(void) {
- INFO("");
- if (!safeToSync() || !getWorkLoop()->inGate())
- return;
- INFO("running");
- OSDictionary *inputDict = dictionaryWithProperties();
- if (!inputDict)
- return;
- OSCollectionIterator *iter = OSCollectionIterator::withCollection(inputDict);
- if (!iter) {
- ERROR("FAILURE! No iterator on input dictionary");
- inputDict->release();
- return;
- }
- OSDictionary *outputDict = OSDictionary::withCapacity(inputDict->getCount());
- while (OSSymbol *key = OSDynamicCast(OSSymbol, iter->getNextObject())) {
- OSObject *value = inputDict->getObject(key);
- const char *keyChar = key->getCStringNoCopy();
- if (const char *guidValueStr = strchr(keyChar, NVRAM_SEPARATOR)) {
- char guidStr[guidValueStr - keyChar + 1];
- strlcpy(guidStr, keyChar, sizeof(guidStr));
- OSDictionary *guidDict = OSDynamicCast(OSDictionary, outputDict->getObject(guidStr));
- if (!guidDict) {
- guidDict = OSDictionary::withCapacity(1);
- outputDict->setObject(guidStr, guidDict);
- guidDict->release();
- }
- if (OSString *nKey = OSString::withCString(guidValueStr + sizeof(NVRAM_SEPARATOR))) {
- guidDict->setObject(nKey, value);
- nKey->release();
- }
- }
- else
- outputDict->setObject(key, value);
- }
- inputDict->release();
- iter->release();
- _changeCount = 0;
- OSSerialize *s = OSSerialize::withCapacity(10000);
- s->addString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
- "<plist version=\"1.0\">\n");
- outputDict->serialize(s);
- outputDict->release();
- s->addString("\n</plist>\n");
- int error = 0;
- vnode_t vp;
- vnode_attr at = {};
- VATTR_SET_ACTIVE(&at, va_data_size);
- if ((error = vnode_open(_filePath->getCStringNoCopy(), (O_CREAT | FWRITE | O_NOFOLLOW), S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, _context)))
- ERROR("Error opening vnode at path %s, errno %d", _filePath->getCStringNoCopy(), error)
- else if ((error = vnode_setattr(vp, &at, _context)))
- ERROR("Error truncating vnode at path %s, errno %d", _filePath->getCStringNoCopy(), error)
- else if ((error = vn_rdwr(UIO_WRITE, vp, s->text(), s->getLength(), 0, UIO_SYSSPACE, IO_NOCACHE | IO_NODELOCKED | IO_UNIT, vfs_context_ucred(_context), (int *)0, vfs_context_proc(_context))))
- ERROR("Error writing to vnode at path %s, errno %d", _filePath->getCStringNoCopy(), error)
- else if ((error = vnode_close(vp, FWASWRITTEN, _context)))
- ERROR("Error closing vnode errno %d", error);
- s->release();
- return;
- }
- bool AppleNVRAM::safeToSync(void) {
- INFO("");
- return _isReady && _filePath && _isAwake && _changeCount;
- }
- IOByteCount AppleNVRAM::savePanicInfo(UInt8 *buffer, IOByteCount length) {
- // kdb_printf("Handling panic(%p, %lu)", buffer, length);
- // IOAddressRange r[2] = {{(IOVirtualAddress)buffer, length}, {(IOVirtualAddress)&length, sizeof(length)}};
- // IOStorageAttributes o = {kIOStorageOptionForceUnitAccess};
- // kdb_printf(", creating descriptor");
- // IOMemoryDescriptor *d = IOMemoryDescriptor::withAddressRanges(r, 2, 0, NULL);
- // kdb_printf(", writing");
- // _panic->write(this, _panicSize - length - sizeof(length), d, &o, (UInt64 *)NULL);
- // kdb_printf(", synchronizing");
- // OSSynchronizeIO();
- // kdb_printf(", releasing\n");
- // d->release();
- // vnode_t _panic;
- // size_t n = strlen(NVRAM_LOC_PANIC) + 5;
- // char *panic = (char *)IOMalloc(n);
- // snprintf(panic, n, "%s.%u", NVRAM_LOC_PANIC, random() % 1000);
- // int error = vnode_open(panic, (O_TRUNC | O_CREAT | FWRITE | O_NOFOLLOW), S_IRUSR | S_IRGRP | S_IROTH, VNODE_LOOKUP_NOFOLLOW, &_panic, _context);
- // if (error)
- // ERROR("failed opening vnode at path %s, errno %d", panic, error)
- // IOFree(panic, n);
- // uio_t u = uio_create(2, 0, UIO_SYSSPACE, UIO_WRITE);
- // uio_addiov(u, (user_addr_t)&length, sizeof(length));
- // uio_addiov(u, (user_addr_t)buffer, length);
- // VNOP_WRITE(_panic, u, IO_NOCACHE|IO_NODELOCKED|IO_UNIT|IO_SYNC|IO_NOAUTH, _context);
- // uio_free(u);
- // vnode_close(_panic, FWASWRITTEN, _context);
- return length;
- }
- IOReturn AppleNVRAM::syncOFVariables(void) {
- INFO("");
- return kIOReturnSuccess;
- }
- void AppleNVRAM::registerNVRAMController(IONVRAMController *nvram) {
- INFO("%p", nvram);
- }
- IOReturn AppleNVRAM::readXPRAM(IOByteCount offset, UInt8 *buffer, IOByteCount length) {
- INFO("%zu, %p, %zu", (size_t)offset, buffer, (size_t)length);
- return kIOReturnUnsupported;
- }
- IOReturn AppleNVRAM::writeXPRAM(IOByteCount offset, UInt8 *buffer, IOByteCount length) {
- INFO("%zu, %p, %zu", (size_t)offset, buffer, (size_t)length);
- return kIOReturnUnsupported;
- }
- IOReturn AppleNVRAM::readNVRAMProperty(IORegistryEntry *entry, const OSSymbol **name, OSData **value) {
- INFO("%s, %p, %p", entry->getName(), name, value);
- return kIOReturnUnsupported;
- }
- IOReturn AppleNVRAM::writeNVRAMProperty(IORegistryEntry *entry, const OSSymbol *name, OSData *value) {
- INFO("%s, %s, %p", entry->getName(), name->getCStringNoCopy(), value);
- return kIOReturnUnsupported;
- }
- OSDictionary *AppleNVRAM::getNVRAMPartitions(void) {
- INFO("");
- return 0;
- }
- IOReturn AppleNVRAM::readNVRAMPartition(const OSSymbol *partitionID, IOByteCount offset, UInt8 *buffer, IOByteCount length) {
- INFO("%s, %zu, %p, %zu", partitionID->getCStringNoCopy(), (size_t)offset, buffer, (size_t)length);
- return kIOReturnNotFound;
- }
- IOReturn AppleNVRAM::writeNVRAMPartition(const OSSymbol *partitionID, IOByteCount offset, UInt8 *buffer, IOByteCount length) {
- INFO("%s, %zu, %p, %zu", partitionID->getCStringNoCopy(), (size_t)offset, buffer, (size_t)length);
- return kIOReturnSuccess;
- }
- #pragma mark Private
- bool AppleNVRAM::BSDReady(void *target, void *refCon, IOService *newService, IONotifier *notifier) {
- notifier->remove();
- AppleNVRAM *it = (AppleNVRAM *)target;
- if (OSDictionary *n = nameMatching("disk0s1")) {
- if (IOMedia *m = OSDynamicCast(IOMedia, copyMatchingService(n))) {
- it->_panic = m->getProvider();
- it->_panicSize = m->getSize();
- m->release();
- }
- n->release();
- return true;
- }
- return false;
- }
- IOReturn AppleNVRAM::_sync(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3) {
- ((AppleNVRAM *)owner)->sync();
- return kIOReturnSuccess;
- }
- void AppleNVRAM::copyEntryProperties(const char *prefix, IORegistryEntry *entry) {
- IORegistryEntry *child;
- if (!entry)
- return;
- if (OSIterator *iterator = entry->getChildIterator(gIODTPlane)) {
- while ((child = OSDynamicCast(IORegistryEntry, iterator->getNextObject())) != NULL) {
- const char *name = child->getName();
- if (prefix) {
- if (strcmp(NVRAM_KEY_UID, prefix)) {
- size_t size = strlen(prefix) + sizeof(NVRAM_SEPARATOR) + strlen(name) + 1;
- char *newPrefix = (char *)IOMalloc(size);
- snprintf(newPrefix, size, "%s%c%s", prefix, NVRAM_SEPARATOR, name);
- copyEntryProperties(newPrefix, child);
- IOFree(newPrefix, size);
- }
- else {
- OSString *key = OSString::withCString(child->getName());
- handleSetting(key, kOSBooleanTrue);
- key->release();
- }
- }
- else
- copyEntryProperties(name, child);
- }
- iterator->release();
- }
- OSDictionary *properties = entry->dictionaryWithProperties();
- OSCollectionIterator *iter;
- if (!(iter = OSCollectionIterator::withCollection(properties))) {
- OSSafeRelease(properties);
- return;
- }
- bool result = true;
- while (result) {
- const OSSymbol *key;
- if (!(key = OSDynamicCast(OSSymbol, iter->getNextObject())))
- break;
- if (key->isEqualTo("name"))
- continue;
- OSObject *object;
- if (!(object = properties->getObject(key)))
- continue;
- if (prefix) {
- if (strcmp(NVRAM_KEY_UID, prefix)) {
- size_t size = strlen(prefix) + sizeof(NVRAM_SEPARATOR) + strlen(key->getCStringNoCopy()) + 1;
- char *newKey = (char *)IOMalloc(size);
- snprintf(newKey, size, "%s%c%s", prefix, NVRAM_SEPARATOR, key->getCStringNoCopy());
- setProperty(OSSymbol::withCString(newKey), object);
- IOFree(newKey, size);
- }
- else
- handleSetting(key, object);
- }
- else
- setProperty(key, object);
- }
- iter->release();
- properties->release();
- }
- void AppleNVRAM::handleSetting(const OSObject *object, const OSObject *value) {
- OSString *key = OSDynamicCast(OSString, object);
- if (key)
- INFO("Handling key %s", key->getCStringNoCopy())
- else {
- ERROR("Unknown key");
- return;
- }
- if (key->isEqualTo(NVRAM_COMMAND_FILE)) {
- OSString *str;
- if ((str = OSDynamicCast(OSString, value)))
- str->retain();
- else if (OSData *dat = OSDynamicCast(OSData, value))
- str = OSString::withCString((const char *)dat->getBytesNoCopy());
- else
- return;
- INFO("Setting path to %s", str->getCStringNoCopy());
- OSString *filepath = _filePath;
- _filePath = str;
- OSSafeRelease(filepath);
- }
- else if (key->isEqualTo(NVRAM_COMMAND_MLB)) {
- OSBoolean *shouldgen = OSDynamicCast(OSBoolean, value);
- if (shouldgen && shouldgen->isTrue()) {
- INFO("Generating MLB");
- IORegistryEntry *root = IORegistryEntry::fromPath("/", gIODTPlane);
- if (!root)
- return;
- OSString *serial = OSDynamicCast(OSString, root->getProperty(kIOPlatformSerialNumberKey));
- root->release();
- if (!serial)
- return;
- size_t serialLen = strlen(serial->getCStringNoCopy()), mlbLen = serialLen == 11 ? 13 : serialLen == 12 ? 17 : serialLen;
- char buffer[mlbLen + 1];
- strlcpy(buffer, serial->getCStringNoCopy(), sizeof(buffer));
- gen_random(buffer + serialLen, mlbLen - serialLen);
- const OSSymbol *sym = OSSymbol::withCString(NVRAM_KEY_MLB);
- OSData *value = OSData::withBytes(buffer, (int)sizeof(buffer));
- setProperty(sym, value);
- sym->release();
- value->release();
- }
- }
- else if (key->isEqualTo(NVRAM_COMMAND_ROM)) {
- OSBoolean *shouldgen = OSDynamicCast(OSBoolean, value);
- if (shouldgen && shouldgen->isTrue()) {
- INFO("Generating ROM");
- char buffer[6] = {(char)random(), (char)random(), (char)random(), (char)random(), (char)random(), (char)random()};
- const OSSymbol *sym = OSSymbol::withCString(NVRAM_KEY_ROM);
- OSData *value = OSData::withBytes(buffer, sizeof(buffer));
- setProperty(sym, value);
- sym->release();
- value->release();
- }
- }
- else if (key->isEqualTo(NVRAM_COMMAND_LOG)) {
- if (OSBoolean *shouldlog = OSDynamicCast(OSBoolean, value)) {
- _shouldLog = shouldlog == kOSBooleanTrue;
- INFO("Setting logging to %s", _shouldLog ? "enabled" : "disabled");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement