IOPlatformSupport.c [plain text]
#if !TARGET_OS_EMBEDDED
#include "IOPlatformSupportPrivate.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <notify.h>
#if 0
#define DLOG(format) syslog(LOG_DEBUG, "IONTSLib: " format)
#define DLOG1(format, args ...) syslog(LOG_DEBUG, "IONTSLib: " format, args)
#define DLOG_ERROR(format) syslog(LOG_ERR, "IONTSLib: " format)
#define DLOG_ERROR1(format, args ...) syslog(LOG_ERR, "IONTSLib: " format, args)
#else
#define DLOG(format)
#define DLOG1(format, args ...)
#define DLOG_ERROR(format)
#define DLOG_ERROR1(format, args ...)
#endif
static Boolean CopyModel(char** model, uint32_t *majorRev, uint32_t *minorRev)
{
int mib[2];
char *machineModel; char *revStr;
int count;
unsigned long modelLen;
Boolean success = true;
size_t length = 1024;
if (!model || !majorRev || !minorRev) {
DLOG_ERROR("CopyModel: Passing NULL arguments\n");
return false;
}
machineModel = malloc(length);
mib[0] = CTL_HW;
mib[1] = HW_MODEL;
if (sysctl(mib, 2, machineModel, &length, NULL, 0)) {
printf("CopyModel: sysctl (error %d)\n", errno);
success = false;
goto exit;
}
modelLen = strcspn(machineModel, "0123456789");
if (modelLen == 0) {
DLOG_ERROR("CopyModel: Could not find machine model name\n");
success = false;
goto exit;
}
*model = strndup(machineModel, modelLen);
if (*model == NULL) {
DLOG_ERROR("CopyModel: Could not find machine model name\n");
success = false;
goto exit;
}
*majorRev = 0;
*minorRev = 0;
revStr = strpbrk(machineModel, "0123456789");
if (!revStr) {
DLOG_ERROR("CopyModel: Could not find machine version number, inferred value is 0,0\n");
success = true;
goto exit;
}
count = sscanf(revStr, "%d,%d", majorRev, minorRev);
if (count < 2) {
DLOG_ERROR("CopyModel: Could not find machine version number\n");
if (count<1) {
*majorRev = 0;
}
*minorRev = 0;
success = true;
goto exit;
}
exit:
if (machineModel) free(machineModel);
if (!success) {
if (*model) free(*model);
*model = NULL;
*majorRev = 0;
*minorRev = 0;
}
return success;
}
Boolean IOSMCKeyProxyPresent()
{
char* model = NULL; uint32_t majorRev;
uint32_t minorRev;
Boolean success = false;
Boolean modelFound = CopyModel(&model, &majorRev, &minorRev);
if (!modelFound) {
DLOG_ERROR("IOSMCKeyProxySupported: Could not find machine model\n");
return false;
}
if (!strncmp(model, "MacBookPro", 10) && (majorRev <=7))
goto exit;
if (!strncmp(model, "MacBookAir", 10) && (majorRev <=2))
goto exit;
if (!strncmp(model, "MacBook", 10))
goto exit;
if (!strncmp(model, "iMac", 10) && (majorRev <=11))
goto exit;
if (!strncmp(model, "Macmini", 10) && (majorRev <=3))
goto exit;
if (!strncmp(model, "MacPro", 10) && (majorRev <=5))
goto exit;
if (!strncmp(model, "Xserve", 10))
goto exit;
success = true;
DLOG("Machine appears to have SMC Key Proxy\n");
exit:
if (model) free(model);
return success;
}
Boolean IONoteToSelfSupported()
{
char* model = NULL; uint32_t majorRev;
uint32_t minorRev;
Boolean success = false;
Boolean modelFound = CopyModel(&model, &majorRev, &minorRev);
if (!modelFound) {
DLOG_ERROR("IONoteToSelfSupported: Could not find machine model\n");
return false;
}
if (!strncmp(model, "MacBookPro", 10) && (majorRev < 5 ||
(majorRev == 5 && minorRev <= 2)))
goto exit;
if (!strncmp(model, "MacBookAir", 10) && (majorRev <=2))
goto exit;
if (!strncmp(model, "MacBook", 10) && (majorRev <=5))
goto exit;
if (!strncmp(model, "iMac", 10) && (majorRev <=9))
goto exit;
if (!strncmp(model, "Macmini", 10) && (majorRev <=3))
goto exit;
if (!strncmp(model, "MacPro", 10))
goto exit;
if (!strncmp(model, "Xserve", 10))
goto exit;
success = true;
DLOG("Machine appears to be capable of Note To Self\n");
exit:
if (model) free(model);
return success;
}
Boolean IOAuthenticatedRestartSupported()
{
return IONoteToSelfSupported() || IOSMCKeyProxyPresent();
}
static CFTypeRef _copyRootDomainProperty(CFStringRef key)
{
io_registry_entry_t platformReg = IO_OBJECT_NULL;
CFTypeRef obj = NULL;
platformReg = IORegistryEntryFromPath( kIOMasterPortDefault,
kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain");
if (IO_OBJECT_NULL != platformReg)
{
obj = IORegistryEntryCreateCFProperty(
platformReg,
key,
kCFAllocatorDefault,
kNilOptions);
}
IOObjectRelease(platformReg);
return obj;
}
IOReturn IOPlatformCopyFeatureDefault(
CFStringRef platformSettingKey,
CFTypeRef *outValue)
{
CFDictionaryRef platformFeatures = NULL;
CFTypeRef returnObj = NULL;
if (!platformSettingKey || !outValue) {
return kIOReturnBadArgument;
}
platformFeatures = _copyRootDomainProperty(CFSTR("IOPlatformFeatureDefaults"));
if (platformFeatures) {
returnObj = CFDictionaryGetValue(platformFeatures, platformSettingKey);
if (returnObj) {
*outValue = CFRetain(returnObj);
}
CFRelease(platformFeatures);
}
if (*outValue) {
return kIOReturnSuccess;
} else {
return kIOReturnUnsupported;
}
}
IOReturn IOPlatformCopyFeatureActive(
CFStringRef platformSettingKey,
CFTypeRef *outValue)
{
if (!platformSettingKey || !outValue) {
return kIOReturnBadArgument;
}
if (CFEqual(platformSettingKey, kIOPlatformTCPKeepAliveDuringSleep))
{
int keepAliveIsValid = 0;
keepAliveIsValid = IOPMGetValueInt(kIOPMTCPKeepAliveIsActive);
if (keepAliveIsValid) {
*outValue = kCFBooleanTrue;
} else {
*outValue = kCFBooleanFalse;
}
return kIOReturnSuccess;
}
else if (CFEqual(platformSettingKey, CFSTR(kIOPMWakeOnLANKey))) {
if (IOPMGetValueInt(kIOPMWakeOnLanIsActive)) {
*outValue = kCFBooleanTrue;
} else {
*outValue = kCFBooleanFalse;
}
return kIOReturnSuccess;
}
else {
return IOPlatformCopyFeatureDefault(platformSettingKey, outValue);
}
}
typedef union __attribute__((packed)) {
uint32_t rgb;
struct {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t reserved;
} component_v1;
struct {
uint8_t blue;
uint8_t green;
uint8_t red;
uint8_t reserved;
} component_v2;
} IOPlatformDeviceColorRGB;
typedef struct __attribute__((packed)) {
uint8_t minor_version;
uint8_t major_version;
uint8_t reserved_2;
uint8_t reserved_3;
IOPlatformDeviceColorRGB device_enclosure;
IOPlatformDeviceColorRGB cover_glass;
uint8_t reserved_C;
uint8_t reserved_D;
uint8_t reserved_E;
uint8_t reserved_F;
} IOPlatformDeviceColors;
IOReturn IOPlatformGetDeviceColor(
CFStringRef whichColor,
uint8_t * red, uint8_t * green, uint8_t * blue )
{
IOReturn ret = kIOReturnNotFound;
if (!whichColor)
return kIOReturnBadArgument;
if (CFEqual(whichColor, kIOPlatformDeviceEnclosureColorKey))
{
io_registry_entry_t platform = IO_OBJECT_NULL;
CFTypeRef prop = NULL;
platform = IORegistryEntryFromPath( kIOMasterPortDefault,
kIODeviceTreePlane ":/efi/platform");
if (IO_OBJECT_NULL != platform)
{
prop = IORegistryEntryCreateCFProperty(
platform,
CFSTR("device-colors"),
kCFAllocatorDefault,
kNilOptions);
IOObjectRelease(platform);
}
if (prop && (CFGetTypeID(prop) == CFDataGetTypeID()))
{
CFDataRef data = (typeof(data)) prop;
const IOPlatformDeviceColors * colors = (typeof(colors)) CFDataGetBytePtr(data);
if ((CFDataGetLength(data) == sizeof(IOPlatformDeviceColors)) &&
colors && (colors->major_version == 2))
{
if (red) *red = colors->device_enclosure.component_v2.red;
if (green) *green = colors->device_enclosure.component_v2.green;
if (blue) *blue = colors->device_enclosure.component_v2.blue;
ret = kIOReturnSuccess;
}
}
if (prop) CFRelease(prop);
}
return ret;
}
#endif