BUKTOP
BUKTOP

Reputation: 971

How to store kext parameters between runs?

A question about kext development. My IOKit kext has some parameters that could be changed in the runtime. Cannot find any clue, how could I store these parameters in order to retrieve and use them on the next kext run? Like, in a file or maybe nvram (preferred)? Or another persistent storage I am not aware about yet?

A small remark: my kext has OSBundleRequired=Root, so I suppose root fs is available when kernel loads it. But i also think that NVRAM is preferable because it is easier to manage for an end user.

TL;DR My kext has a bool parameter that could be changed during kext's lifecycle in runtime. I need to store this parameter on the kext stop, and retrieve and use it in the kext on the kext's start. I'd like to use NVRAM to store it. How it could be done?

Upvotes: -4

Views: 72

Answers (1)

BUKTOP
BUKTOP

Reputation: 971

I found the answer here. This is an MVE for an octet (i. e. 8bit byte aka uint8_t, requires euid=0 of course):

For a userspace app:

main.c:

#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>

int main(int argc, char * argv[])
{   const char * serviceName = "AppleEFINVRAM";
    const char * keyName = "MytestKey";

    io_service_t ioService = IOServiceGetMatchingService(kIOMainPortDefault,
                             IOServiceMatching(serviceName));

    if (!ioService)
    {   printf("Service \"%s\" not found\n", serviceName);
        return (1);
    }
    CFStringRef ioKey = CFStringCreateWithCString(kCFAllocatorDefault,
                        keyName,
                        CFStringGetSystemEncoding());

    CFNumberRef ioNumValue;
    uint8_t value = 0;
    CFTypeRef ioValue = IORegistryEntryCreateCFProperty(ioService, ioKey, kCFAllocatorDefault, 0);
    if (ioValue && CFGetTypeID(ioValue) == CFNumberGetTypeID())
    {   ioNumValue = ioValue;
        CFNumberGetValue(ioNumValue, kCFNumberSInt8Type, &value);
        printf("Got key, value=%d\n", (int)value);
    }
    if (ioValue) CFRelease(ioValue);

    value++;

    printf("Value will be set to %d\n", (int)value);
    ioNumValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &value);

    kern_return_t res = IORegistryEntrySetCFProperty(ioService, ioKey, ioNumValue);
    if (res != KERN_SUCCESS)
    {   printf("Cannot set value, error 0x%X\n", res);
    }
    CFRelease(ioNumValue);

    IOObjectRelease(ioService);

    return (0);
}

Makefile:

nvramTest: main.c
        ${CC} $^ -framework CoreFoundation -framework IOKit -o $@

For a kext:

void GenericPower::readFromNvram(void)
{   IORegistryEntry *nvram = IORegistryEntry::fromPath("/options", gIODTPlane);
    if (!nvram || !OSDynamicCast(IODTNVRAM, nvram))
    {   IOLog("readFromNVRAM: failed to read NVRAM\n");
        OSSafeReleaseNULL(nvram);
        return;
    }

    OSData *storedMode = OSDynamicCast(OSData, nvram->getProperty(ENABLED_PROP_NAME));
    if (storedMode == nullptr || storedMode->getLength() <= 0)
    {   IOLog("readFromNVRAM: key " ENABLED_PROP_NAME " not found, defaulting to \"disabled\"\n");
        isEnabled = false;
        OSSafeReleaseNULL(nvram);
        return;
    }
    const  uint8_t * storedModeData = static_cast<const uint8_t *>(storedMode->getBytesNoCopy());
    IOLog("readFromNVRAM: stored value for \""  ENABLED_PROP_NAME "\" is (%d bytes): %2.2X...\n", (int)storedMode->getLength(), (unsigned int)storedModeData[0]);

    isEnabled = storedModeData[0];
    IOLog("readFromNVRAM: stored value for \""  ENABLED_PROP_NAME "\" is %s\n", isEnabled ? "ON" : "OFF");

    OSSafeReleaseNULL(nvram);
}

void GenericPower::writeToNvram(void)
{   IORegistryEntry *nvram = IORegistryEntry::fromPath("/options", gIODTPlane);
    if (!nvram || !OSDynamicCast(IODTNVRAM, nvram))
    {   IOLog("writeToNVRAM: failed to read NVRAM\n");
        OSSafeReleaseNULL(nvram);
        return;
    }

    OSData *storedMode = OSData::withBytes(isEnabled ? "\x01" : "\x00", 1);
    if (!nvram->setProperty(ENABLED_PROP_NAME, storedMode))
    {   IOLog("writeToNVRAM: failed to write NVRAM\n");
    }

    OSSafeReleaseNULL(storedMode);
    OSSafeReleaseNULL(nvram);
}

Upvotes: 1

Related Questions