#include <kern/debug.h>
#include <pexpert/boot.h>
#include <pexpert/pexpert.h>
+#include <sys/csr.h>
#define super IOService
// From Apple CHRP Spec
#define NVRAM_CHRP_SIG_SYSTEM 0x70
#define NVRAM_CHRP_SIG_CONFIG 0x71
-#define NVRAM_CHRP_SIG_FREESPACE 0x7F
-#define NVRAM_CHRP_PARTITION_NAME_COMMON "common"
-#define NVRAM_CHRP_PARTITION_NAME_SYSTEM "system"
-#define NVRAM_CHRP_PARTITION_NAME_SYSTEM_LEGACY "secure"
-#define NVRAM_CHRP_PARTITION_NAME_FREESPACE "\x77\x77\x77\x77\x77\x77\x77\x77\x77\x77\x77\x77"
+#define NVRAM_CHRP_PARTITION_NAME_COMMON_V1 "common"
+#define NVRAM_CHRP_PARTITION_NAME_SYSTEM_V1 "system"
+#define NVRAM_CHRP_PARTITION_NAME_COMMON_V2 "2common"
+#define NVRAM_CHRP_PARTITION_NAME_SYSTEM_V2 "2system"
#define NVRAM_CHRP_LENGTH_BLOCK_SIZE 0x10 // CHRP length field is in 16 byte blocks
IOLockUnlock(_controllerLock); \
})
-#define NVRAMLOCK() \
-({ \
+#define NVRAMREADLOCK() \
+({ \
if (preemption_enabled() && !panic_active()) \
- IOLockLock(_variableLock); \
+ IORWLockRead(_variableLock); \
})
-#define NVRAMUNLOCK() \
-({ \
+#define NVRAMWRITELOCK() \
+({ \
if (preemption_enabled() && !panic_active()) \
- IOLockUnlock(_variableLock); \
+ IORWLockWrite(_variableLock); \
})
-#define NVRAMLOCKASSERT() \
-({ \
- if (preemption_enabled() && !panic_active()) \
- IOLockAssert(_variableLock, kIOLockAssertOwned); \
+#define NVRAMUNLOCK() \
+({ \
+ if (preemption_enabled() && !panic_active()) \
+ IORWLockUnlock(_variableLock); \
+})
+
+#define NVRAMLOCKASSERTHELD() \
+({ \
+ if (preemption_enabled() && !panic_active()) \
+ IORWLockAssert(_variableLock, kIORWLockAssertHeld); \
})
+#define NVRAMLOCKASSERTEXCLUSIVE() \
+({ \
+ if (preemption_enabled() && !panic_active()) \
+ IORWLockAssert(_variableLock, kIORWLockAssertWrite); \
+})
+
+enum NVRAMPartitionType {
+ kIONVRAMPartitionSystem,
+ kIONVRAMPartitionCommon
+};
+
typedef struct {
- const char *name;
+ NVRAMPartitionType type;
UInt32 offset;
UInt32 size;
OSSharedPtr<OSDictionary> &dict;
UUID_DEFINE(gAppleNVRAMGuid, 0x7C, 0x43, 0x61, 0x10, 0xAB, 0x2A, 0x4B, 0xBB, 0xA8, 0x80, 0xFE, 0x41, 0x99, 0x5C, 0x9F, 0x82);
static bool gNVRAMLogging = false;
+static bool gInternalBuild = false;
// allowlist variables from macboot that need to be set/get from system region if present
static const char * const gNVRAMSystemList[] = {
- "adbe-tunable",
- "adbe-tunables",
- "adfe-tunables",
- "alamo-path",
- "alt-boot-volume",
- "ASMB",
- "atc0",
- "atc1",
+ "allow-root-hash-mismatch",
"auto-boot",
"auto-boot-halt-stage",
- "auto-boot-once",
- "auto-boot-usb",
- "auxkc-path",
- "backlight-level",
- "backlight-nits",
"base-system-path",
"boot-args",
- "boot-breadcrumbs",
"boot-command",
- "boot-device",
"boot-image",
- "boot-partition",
- "boot-path",
- "boot-ramdisk",
- "boot-script",
- "boot-volume",
"bootdelay",
- "bt1addr",
- "btaddr",
- "cam-use-ext-ldo",
- "CLCG_override",
"com.apple.System.boot-nonce",
- "com.apple.System.rtc-offset",
- "com.apple.System.tz0-size",
- "core-bin-offset",
- "cpu-bin-offset",
"darkboot",
- "DClr_override",
- "dcp-auto-boot",
- "debug-gg",
- "debug-soc",
- "debug-uarts",
- "diags-path",
- "disable-boot-wdt",
- "display-color-space",
- "display-timing",
- "display-vsh-comp",
- "dpcd-max-brightness",
- "dtdump",
- "dtdump-path",
- "e75",
"emu",
- "enable-auth-debug",
- "enable-jop",
- "enable-marconi",
- "enable-upgrade-fallback",
- "enforce-iuob",
- "eth1addr",
- "ethaddr",
- "failboot-breadcrumbs",
- "fixed-lcm-boost",
- "force-ctrr-lock",
- "force-upgrade-fail",
- "fuos-path",
- "hib-ui-force",
- "hibhack-test-hmac",
- "iboot-data",
- "iboot-failure-reason",
- "iboot-failure-reason-str",
- "iboot-failure-volume",
- "iboot1-precommitted",
- "idle-off",
- "is-tethered",
- "kaslr-off",
- "kaslr-slide",
- "kis-rsm",
- "knobs",
- "loadaddr",
- "memmapdump",
- "mipi-bridge-cmd-verify",
- "mipi-bridge-poll-cmd-fifo",
- "no-ctrr",
- "one-time-boot-command",
- "osenvironment",
- "ota-breadcrumbs",
- "ota-outcome",
- "panicmedic",
- "panicmedic-threshold",
- "panicmedic-timestamps",
- "phleet-path",
- "pinot-panel-id",
- "pintoaddr",
+ "one-time-boot-command", // Needed for diags customer install flows
"policy-nonce-digests",
- "preserve-debuggability",
"prevent-restores", // Keep for factory <rdar://problem/70476321>
"prev-lang:kbd",
- "ramrod-kickstart-aces",
- "rbdaddr0",
- "rbm-path",
- "reconfig-behavior",
- "reconfig-breakpoints",
- "recovery-boot-mode",
- "recovery-breadcrumbs",
- "restored-host-timeout",
"root-live-fs",
- "rtos-path",
- "soc-bin-offset",
- "StartupMute",
- "StartupMuteAccessibility",
- "storage-prev-assert",
- "storage-prev-assert-stored",
- "summit-panel-id",
"SystemAudioVolume",
"SystemAudioVolumeExtension",
"SystemAudioVolumeSaved",
- "tz0-size-override",
- "upgrade-fallback-boot-command",
- "upgrade-retry",
- "usb-enabled",
- "wifi1addr",
- "wifiaddr",
nullptr
};
.p.Bits.NeverAllowedToDelete = 1},
{"boot-image", .p.Bits.UserWrite = 1},
{"com.apple.System.fp-state", .p.Bits.KernelOnly = 1},
- {"policy-nonce-digests", .p.Bits.ResetNVRAMOnlyDelete = 1},
+ {"policy-nonce-digests", .p.Bits.ResetNVRAMOnlyDelete = 1}, // Deleting this via user triggered obliterate leave J273a unable to boot
{"security-password", .p.Bits.RootRequired = 1},
#if !defined(__x86_64__)
{"acc-cm-override-count", .p.Bits.KernelOnly = 1},
{"acc-mb-ld-lifetime", .p.Bits.KernelOnly = 1},
{"backlight-level", .p.Bits.UserWrite = 1},
+ {"backlight-nits", .p.Bits.UserWrite = 1},
{"com.apple.System.boot-nonce", .p.Bits.KernelOnly = 1},
{"com.apple.System.sep.art", .p.Bits.KernelOnly = 1},
{"darkboot", .p.Bits.UserWrite = 1},
return true;
}
+#if defined(DEBUG) || defined(DEVELOPMENT)
+static const char *
+getNVRAMOpString(IONVRAMOperation op)
+{
+ switch (op) {
+ case kIONVRAMOperationRead:
+ return "Read";
+ case kIONVRAMOperationWrite:
+ return "Write";
+ case kIONVRAMOperationDelete:
+ return "Delete";
+ case kIONVRAMOperationObliterate:
+ return "Obliterate";
+ case kIONVRAMOperationReset:
+ return "Reset";
+ default:
+ return "Unknown";
+ }
+}
+#endif
+
static bool
verifyPermission(IONVRAMOperation op, const uuid_t *varGuid, const char *varName)
{
VariablePermission perm;
- bool kernel, admin, writeEntitled, readEntitled, allowList, systemGuid, systemEntitled;
+ bool kernel, admin, writeEntitled, readEntitled, allowList, systemGuid, systemEntitled, systemInternalEntitled, systemAllow;
+ bool ok = false;
perm = getVariablePermission(varName);
if (perm.Bits.KernelOnly) {
DEBUG_INFO("KernelOnly access for %s, kernel=%d\n", varName, kernel);
- return kernel;
+ ok = kernel;
+ goto exit;
}
- allowList = variableInAllowList(varName);
- systemGuid = uuid_compare(*varGuid, gAppleSystemVariableGuid) == 0;
- admin = IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege) == kIOReturnSuccess;
- writeEntitled = IOTaskHasEntitlement(current_task(), kIONVRAMWriteAccessKey);
- readEntitled = IOTaskHasEntitlement(current_task(), kIONVRAMReadAccessKey);
- systemEntitled = IOTaskHasEntitlement(current_task(), kIONVRAMSystemAllowKey) || kernel;
+ allowList = variableInAllowList(varName);
+ systemGuid = uuid_compare(*varGuid, gAppleSystemVariableGuid) == 0;
+ admin = IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege) == kIOReturnSuccess;
+ writeEntitled = IOTaskHasEntitlement(current_task(), kIONVRAMWriteAccessKey);
+ readEntitled = IOTaskHasEntitlement(current_task(), kIONVRAMReadAccessKey);
+ systemEntitled = IOTaskHasEntitlement(current_task(), kIONVRAMSystemAllowKey);
+ systemInternalEntitled = IOTaskHasEntitlement(current_task(), kIONVRAMSystemInternalAllowKey);
+
+ systemAllow = systemEntitled || (systemInternalEntitled && gInternalBuild) || kernel;
switch (op) {
case kIONVRAMOperationRead:
if (kernel || admin || readEntitled || perm.Bits.FullAccess) {
- return true;
+ ok = true;
}
break;
if (kernel || perm.Bits.UserWrite || admin || writeEntitled) {
if (systemGuid) {
if (allowList) {
- if (!systemEntitled) {
+ if (!systemAllow) {
DEBUG_ERROR("Allowed write to system region when NOT entitled for %s\n", varName);
}
- } else if (!systemEntitled) {
+ } else if (!systemAllow) {
DEBUG_ERROR("Not entitled for system region writes for %s\n", varName);
break;
}
}
- return true;
+ ok = true;
}
break;
} else if ((op == kIONVRAMOperationObliterate) && perm.Bits.ResetNVRAMOnlyDelete) {
DEBUG_INFO("Not allowed to obliterate %s\n", varName);
break;
+ } else if ((op == kIONVRAMOperationDelete) && perm.Bits.ResetNVRAMOnlyDelete) {
+ DEBUG_INFO("Only allowed to delete %s via NVRAM reset\n", varName);
+ break;
}
if (kernel || perm.Bits.UserWrite || admin || writeEntitled) {
if (systemGuid) {
if (allowList) {
- if (!systemEntitled) {
+ if (!systemAllow) {
DEBUG_ERROR("Allowed delete to system region when NOT entitled for %s\n", varName);
}
- } else if (!systemEntitled) {
+ } else if (!systemAllow) {
DEBUG_ERROR("Not entitled for system region deletes for %s\n", varName);
break;
}
}
- return true;
+ ok = true;
}
break;
}
- DEBUG_INFO("Permission for %s denied, kernel=%d, admin=%d, writeEntitled=%d, readEntitled=%d, systemGuid=%d, systemEntitled=%d\n",
- varName, kernel, admin, writeEntitled, readEntitled, systemGuid, systemEntitled);
- return false;
+exit:
+ DEBUG_INFO("Permission for %s of %s %s: kernel=%d, admin=%d, writeEntitled=%d, readEntitled=%d, systemGuid=%d, systemEntitled=%d, systemInternalEntitled=%d, UserWrite=%d\n",
+ getNVRAMOpString(op), varName, ok ? "granted" : "denied", kernel, admin, writeEntitled, readEntitled, systemGuid, systemEntitled, systemInternalEntitled, perm.Bits.UserWrite);
+ return ok;
}
static bool
{
uuid_string_t temp = {0};
size_t keyLen = strlen(key);
- bool result = false;
+ bool ok = false;
const char *name = key;
uuid_t guid;
if ((uuid_parse(temp, guid) == 0) &&
(key[sizeof(temp) - 1] == ':')) {
name = key + sizeof(temp);
- result = true;
+ ok = true;
}
}
if (guidResult) {
- result ? uuid_copy(*guidResult, guid) : uuid_copy(*guidResult, gAppleNVRAMGuid);
+ ok ? uuid_copy(*guidResult, guid) : uuid_copy(*guidResult, gAppleNVRAMGuid);
}
if (nameResult) {
*nameResult = name;
return false;
}
+static bool
+skipKey(const OSSymbol *aKey)
+{
+ return aKey->isEqualTo(kIOClassNameOverrideKey) ||
+ aKey->isEqualTo(kIOBSDNameKey) ||
+ aKey->isEqualTo(kIOBSDNamesKey) ||
+ aKey->isEqualTo(kIOBSDMajorKey) ||
+ aKey->isEqualTo(kIOBSDMinorKey) ||
+ aKey->isEqualTo(kIOBSDUnitKey);
+}
+
+// ************************** IODTNVRAMVariables ****************************
+
// private IOService based class for publishing distinct dictionary properties on
// for easy ioreg access since the serializeProperties call is overloaded and is used
// as variable access
OSDeclareDefaultStructors(IODTNVRAMVariables)
private:
IODTNVRAM *_provider;
- OSDictionary *_properties;
+ OSDictionary *_variables;
uuid_t _guid;
public:
- bool init(const uuid_t *guid);
- virtual bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
- virtual IOReturn setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE;
- virtual bool serializeProperties(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
+ bool init(const uuid_t *guid);
+ virtual bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn setVariables(OSObject * properties);
+
+ virtual bool serializeProperties(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
+ virtual OSPtr<OSObject> copyProperty(const OSSymbol *aKey) const APPLE_KEXT_OVERRIDE;
+ virtual OSObject *getProperty(const OSSymbol *aKey) const APPLE_KEXT_OVERRIDE;
+ virtual bool setProperty(const OSSymbol *aKey, OSObject *anObject) APPLE_KEXT_OVERRIDE;
+ virtual IOReturn setProperties(OSObject *properties) APPLE_KEXT_OVERRIDE;
+ virtual void removeProperty(const OSSymbol *aKey) APPLE_KEXT_OVERRIDE;
};
OSDefineMetaClassAndStructors(IODTNVRAMVariables, IOService)
bool
IODTNVRAMVariables::init(const uuid_t *guid)
{
- require(super::init(), error);
- require(guid, error);
+ if (!super::init()) {
+ return false;
+ }
+
+ if (guid == nullptr) {
+ return false;
+ }
uuid_copy(_guid, *guid);
return true;
-
-error:
- return false;
}
bool
IODTNVRAMVariables::start(IOService * provider)
{
- require(IOService::start(provider), error);
+ if (!IOService::start(provider)) {
+ goto error;
+ }
- require(_provider = OSDynamicCast(IODTNVRAM, provider), error);
+ _provider = OSDynamicCast(IODTNVRAM, provider);
+ if (_provider == nullptr) {
+ goto error;
+ }
registerService();
}
IOReturn
-IODTNVRAMVariables::setProperties(OSObject * properties)
+IODTNVRAMVariables::setVariables(OSObject * variables)
{
- if (OSDynamicCast(OSDictionary, properties)) {
- OSSafeReleaseNULL(_properties);
- _properties = OSDynamicCast(OSDictionary, properties);
- properties->retain();
+ if (OSDynamicCast(OSDictionary, variables)) {
+ OSSafeReleaseNULL(_variables);
+ _variables = OSDynamicCast(OSDictionary, variables);
+ variables->retain();
}
- return IOService::setProperties(properties);
+ return kIOReturnSuccess;
}
bool
const OSSymbol *key;
OSSharedPtr<OSDictionary> dict;
OSSharedPtr<OSCollectionIterator> iter;
- OSSharedPtr<OSDictionary> localProperties(_properties, OSRetain);
- bool result = false;
+ OSSharedPtr<OSDictionary> localVariables(_variables, OSRetain);
+ bool ok = false;
- require(localProperties != nullptr, exit);
+ if (localVariables == nullptr) {
+ goto exit;
+ }
- dict = OSDictionary::withCapacity(localProperties->getCount());
- require_action(dict, exit, DEBUG_ERROR("No dictionary\n"));
+ dict = OSDictionary::withCapacity(localVariables->getCount());
+ if (dict == nullptr) {
+ DEBUG_ERROR("No dictionary\n");
+ goto exit;
+ }
- iter = OSCollectionIterator::withCollection(localProperties.get());
- require_action(iter, exit, DEBUG_ERROR("failed to create iterator\n"));
+ iter = OSCollectionIterator::withCollection(localVariables.get());
+ if (iter == nullptr) {
+ DEBUG_ERROR("failed to create iterator\n");
+ goto exit;
+ }
while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
if (verifyPermission(kIONVRAMOperationRead, &_guid, key)) {
- dict->setObject(key, localProperties->getObject(key));
+ dict->setObject(key, localVariables->getObject(key));
}
}
- result = dict->serialize(s);
+ ok = dict->serialize(s);
exit:
- DEBUG_INFO("result=%d\n", result);
- return result;
+ DEBUG_INFO("ok=%d\n", ok);
+ return ok;
+}
+
+OSPtr<OSObject>
+IODTNVRAMVariables::copyProperty(const OSSymbol *aKey) const
+{
+ if (_provider && !skipKey(aKey)) {
+ DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
+
+ return _provider->copyPropertyWithGUIDAndName(&_guid, aKey->getCStringNoCopy());
+ } else {
+ return nullptr;
+ }
}
+OSObject *
+IODTNVRAMVariables::getProperty(const OSSymbol *aKey) const
+{
+ OSSharedPtr<OSObject> theObject = copyProperty(aKey);
+
+ return theObject.get();
+}
+
+bool
+IODTNVRAMVariables::setProperty(const OSSymbol *aKey, OSObject *anObject)
+{
+ if (_provider) {
+ return _provider->setPropertyWithGUIDAndName(&_guid, aKey->getCStringNoCopy(), anObject);
+ } else {
+ return false;
+ }
+}
+
+IOReturn
+IODTNVRAMVariables::setProperties(OSObject *properties)
+{
+ IOReturn ret = kIOReturnSuccess;
+ OSObject *object;
+ const OSSymbol *key;
+ OSDictionary *dict;
+ OSSharedPtr<OSCollectionIterator> iter;
+
+ if (_provider) {
+ dict = OSDynamicCast(OSDictionary, properties);
+ if (dict == nullptr) {
+ DEBUG_ERROR("Not a dictionary\n");
+ return kIOReturnBadArgument;
+ }
+
+ iter = OSCollectionIterator::withCollection(dict);
+ if (iter == nullptr) {
+ DEBUG_ERROR("Couldn't create iterator\n");
+ return kIOReturnBadArgument;
+ }
+
+ while (ret == kIOReturnSuccess) {
+ key = OSDynamicCast(OSSymbol, iter->getNextObject());
+ if (key == nullptr) {
+ break;
+ }
+
+ object = dict->getObject(key);
+ if (object == nullptr) {
+ continue;
+ }
+
+ ret = setProperty(key, object);
+ }
+ } else {
+ ret = kIOReturnNotReady;
+ }
+
+ DEBUG_INFO("ret=%#08x\n", ret);
+
+ return ret;
+}
+
+void
+IODTNVRAMVariables::removeProperty(const OSSymbol *aKey)
+{
+ if (_provider) {
+ _provider->removePropertyWithGUIDAndName(&_guid, aKey->getCStringNoCopy());
+ }
+}
+
+
+// **************************** IODTNVRAM *********************************
+
bool
IODTNVRAM::init(IORegistryEntry *old, const IORegistryPlane *plane)
{
return false;
}
- _variableLock = IOLockAlloc();
+ PE_parse_boot_argn("nvram-log", &gNVRAMLogging, sizeof(gNVRAMLogging));
+
+#if XNU_TARGET_OS_OSX
+#if CONFIG_CSR
+ gInternalBuild = (csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0);
+#endif // CONFIG_CSR
+#endif // XNU_TARGET_OS_OSX
+
+ DEBUG_INFO("gInternalBuild = %d\n", gInternalBuild);
+
+ _variableLock = IORWLockAlloc();
if (!_variableLock) {
return false;
}
return false;
}
- PE_parse_boot_argn("nvram-log", &gNVRAMLogging, sizeof(gNVRAMLogging));
-
dict = OSDictionary::withCapacity(1);
if (dict == nullptr) {
return false;
DEBUG_INFO("setting controller\n");
+ CONTROLLERLOCK();
_nvramController = nvram;
+ CONTROLLERUNLOCK();
// <rdar://problem/9529235> race condition possible between
// IODTNVRAM and IONVRAMController (restore loses boot-args)
if (!_isProxied) {
- DEBUG_INFO("Proxied NVRAM data\n");
+ DEBUG_INFO("Reading non-proxied NVRAM data\n");
_nvramController->read(0, _nvramImage, _nvramSize);
initNVRAMImage();
}
no_common:
ret = serializeVariables();
- DEBUG_INFO("serializeVariables ret=0x%08x\n", ret);
+ DEBUG_INFO("serializeVariables ret=%#08x\n", ret);
}
void
while (currentOffset < _nvramSize) {
bool common_partition;
bool system_partition;
-
chrp_nvram_header_t * header = (chrp_nvram_header_t *)(_nvramImage + currentOffset);
+ const uint8_t common_v1_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_COMMON_V1};
+ const uint8_t common_v2_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_COMMON_V2};
+ const uint8_t system_v1_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_SYSTEM_V1};
+ const uint8_t system_v2_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_SYSTEM_V2};
currentLength = header->len * NVRAM_CHRP_LENGTH_BLOCK_SIZE;
break;
}
- common_partition = memcmp(header->name, NVRAM_CHRP_PARTITION_NAME_COMMON, strlen(NVRAM_CHRP_PARTITION_NAME_COMMON)) == 0;
- system_partition = (memcmp(header->name, NVRAM_CHRP_PARTITION_NAME_SYSTEM, strlen(NVRAM_CHRP_PARTITION_NAME_SYSTEM)) == 0) ||
- (memcmp(header->name, NVRAM_CHRP_PARTITION_NAME_SYSTEM_LEGACY, strlen(NVRAM_CHRP_PARTITION_NAME_SYSTEM_LEGACY)) == 0);
+ common_partition = (memcmp(header->name, common_v1_name, sizeof(header->name)) == 0) ||
+ (memcmp(header->name, common_v2_name, sizeof(header->name)) == 0);
+ system_partition = (memcmp(header->name, system_v1_name, sizeof(header->name)) == 0) ||
+ (memcmp(header->name, system_v2_name, sizeof(header->name)) == 0);
if (common_partition) {
_commonPartitionOffset = partitionOffset;
OSSharedPtr<OSNumber> partitionOffsetNumber, partitionLengthNumber;
// Construct the partition ID from the signature and name.
- snprintf(partitionID, sizeof(partitionID), "0x%02x,", header->sig);
- strncpy(partitionID + 5, header->name, sizeof(header->name));
+ snprintf(partitionID, sizeof(partitionID), "%#02x,", header->sig);
+ memcpy(partitionID + 5, header->name, sizeof(header->name));
partitionID[17] = '\0';
partitionOffsetNumber = OSNumber::withNumber(partitionOffset, 32);
_systemImage = _nvramImage + _systemPartitionOffset;
}
- DEBUG_ALWAYS("NVRAM : ofPartitionOffset - 0x%x, ofPartitionSize - 0x%x, systemPartitionOffset - 0x%x, systemPartitionSize - 0x%x\n",
+ DEBUG_ALWAYS("NVRAM : commonPartitionOffset - %#x, commonPartitionSize - %#x, systemPartitionOffset - %#x, systemPartitionSize - %#x\n",
(unsigned int) _commonPartitionOffset, (unsigned int) _commonPartitionSize, (unsigned int) _systemPartitionOffset, (unsigned int) _systemPartitionSize);
_lastDeviceSync = 0;
const OSSymbol *key;
OSSharedPtr<OSDictionary> systemDict, commonDict, dict;
OSSharedPtr<OSCollectionIterator> iter;
- bool result = false;
+ bool ok = false;
unsigned int totalCapacity = 0;
- NVRAMLOCK();
+ NVRAMREADLOCK();
if (_commonDict) {
commonDict = OSDictionary::withDictionary(_commonDict.get());
}
}
}
- result = dict->serialize(s);
+ ok = dict->serialize(s);
exit:
- DEBUG_INFO("result=%d\n", result);
+ DEBUG_INFO("ok=%d\n", ok);
- return result;
+ return ok;
}
IOReturn
DEBUG_INFO("Using common dictionary\n");
*dict = _commonDict.get();
}
- } else {
+ return kIOReturnSuccess;
+ } else if (_commonDict != nullptr) {
DEBUG_INFO("Defaulting to common dictionary\n");
*dict = _commonDict.get();
+ return kIOReturnSuccess;
}
- return kIOReturnSuccess;
+ return kIOReturnNotFound;
}
-bool
-IODTNVRAM::handleSpecialVariables(const char *name, uuid_t *guid, OSObject *obj, IOReturn *error)
+IOReturn
+IODTNVRAM::flushDict(const uuid_t *guid, IONVRAMOperation op)
{
IOReturn err = kIOReturnSuccess;
- bool special = false;
- NVRAMLOCKASSERT();
+ if ((_systemDict != nullptr) && (uuid_compare(*guid, gAppleSystemVariableGuid) == 0)) {
+ const OSSymbol *key;
+ OSSharedPtr<OSDictionary> newDict;
+ OSSharedPtr<OSCollectionIterator> iter;
- if (strcmp(name, "ResetNVRam") == 0) {
- DEBUG_INFO("%s requested\n", name);
+ newDict = OSDictionary::withCapacity(_systemDict->getCapacity());
+ iter = OSCollectionIterator::withCollection(_systemDict.get());
+ if ((newDict == nullptr) || (iter == nullptr)) {
+ err = kIOReturnNoMemory;
+ goto exit;
+ }
- if (uuid_compare(*guid, gAppleSystemVariableGuid) == 0) {
- if (_systemDict != nullptr) {
- _systemDict->flushCollection();
+ while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
+ if (!verifyPermission(op, &gAppleSystemVariableGuid, key)) {
+ newDict->setObject(key, _systemDict->getObject(key));
}
-
- _commonDict->flushCollection();
- DEBUG_INFO("system & common dictionary flushed\n");
}
- special = true;
- } else if (strcmp(name, "ObliterateNVRam") == 0) {
- DEBUG_INFO("%s requested\n", name);
+ _systemDict = newDict;
- if ((_systemDict != nullptr) && (uuid_compare(*guid, gAppleSystemVariableGuid) == 0)) {
- const OSSymbol *key;
- OSSharedPtr<OSDictionary> newDict;
- OSSharedPtr<OSCollectionIterator> iter;
+ DEBUG_INFO("system dictionary flushed\n");
+ } else if ((_commonDict != nullptr) && (uuid_compare(*guid, gAppleNVRAMGuid) == 0)) {
+ const OSSymbol *key;
+ OSSharedPtr<OSDictionary> newDict;
+ OSSharedPtr<OSCollectionIterator> iter;
- newDict = OSDictionary::withCapacity(_systemDict->getCapacity());
- iter = OSCollectionIterator::withCollection(newDict.get());
- if ((newDict == nullptr) || (iter == nullptr)) {
- err = kIOReturnNoMemory;
- goto exit;
- }
-
- while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
- const OSSymbol *key = OSDynamicCast(OSSymbol, iter->getNextObject());
- if (key == nullptr) {
- err = kIOReturnNoMemory;
- goto exit;
- }
+ newDict = OSDictionary::withCapacity(_commonDict->getCapacity());
+ iter = OSCollectionIterator::withCollection(_commonDict.get());
+ if ((newDict == nullptr) || (iter == nullptr)) {
+ err = kIOReturnNoMemory;
+ goto exit;
+ }
- if (!verifyPermission(kIONVRAMOperationObliterate, &gAppleSystemVariableGuid, key)) {
- newDict->setObject(key, _systemDict->getObject(key));
- }
+ while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
+ if (!verifyPermission(op, &gAppleNVRAMGuid, key)) {
+ newDict->setObject(key, _commonDict->getObject(key));
}
+ }
- _systemDict = newDict;
+ _commonDict = newDict;
- DEBUG_INFO("system dictionary flushed\n");
- } else if (_commonDict != nullptr) {
- const OSSymbol *key;
- OSSharedPtr<OSDictionary> newDict;
- OSSharedPtr<OSCollectionIterator> iter;
+ DEBUG_INFO("common dictionary flushed\n");
+ }
- newDict = OSDictionary::withCapacity(_commonDict->getCapacity());
- iter = OSCollectionIterator::withCollection(newDict.get());
- if ((newDict == nullptr) || (iter == nullptr)) {
- err = kIOReturnNoMemory;
- goto exit;
- }
+exit:
+ return err;
+}
- while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
- if (!verifyPermission(kIONVRAMOperationObliterate, &gAppleNVRAMGuid, key)) {
- newDict->setObject(key, _commonDict->getObject(key));
- }
- }
+bool
+IODTNVRAM::handleSpecialVariables(const char *name, const uuid_t *guid, const OSObject *obj, IOReturn *error)
+{
+ IOReturn err = kIOReturnSuccess;
+ bool special = false;
- _commonDict = newDict;
+ NVRAMLOCKASSERTEXCLUSIVE();
- DEBUG_INFO("common dictionary flushed\n");
+ // ResetNVRam flushes both regions in one call
+ // Obliterate can flush either separately
+ if (strcmp(name, "ObliterateNVRam") == 0) {
+ err = flushDict(guid, kIONVRAMOperationObliterate);
+ } else if (strcmp(name, "ResetNVRam") == 0) {
+ err = flushDict(&gAppleSystemVariableGuid, kIONVRAMOperationReset);
+
+ if (err != kIOReturnSuccess) {
+ goto exit;
}
- special = true;
+ err = flushDict(&gAppleNVRAMGuid, kIONVRAMOperationReset);
}
exit:
}
OSSharedPtr<OSObject>
-IODTNVRAM::copyProperty(const OSSymbol *aKey) const
+IODTNVRAM::copyPropertyWithGUIDAndName(const uuid_t *guid, const char *name) const
{
IOReturn result;
- const char *variableName;
- uuid_t varGuid;
OSDictionary *dict;
OSSharedPtr<OSObject> theObject = nullptr;
- if (aKey->isEqualTo(kIOBSDNameKey) ||
- aKey->isEqualTo(kIOBSDNamesKey) ||
- aKey->isEqualTo(kIOBSDMajorKey) ||
- aKey->isEqualTo(kIOBSDMinorKey) ||
- aKey->isEqualTo(kIOBSDUnitKey)) {
- // These will never match.
- // Check here and exit to avoid logging spam
- return nullptr;
- }
- DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
-
- parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
-
- result = chooseDictionary(kIONVRAMOperationRead, &varGuid, variableName, &dict);
+ result = chooseDictionary(kIONVRAMOperationRead, guid, name, &dict);
if (result != kIOReturnSuccess) {
+ DEBUG_INFO("No dictionary\n");
goto exit;
}
- if (!verifyPermission(kIONVRAMOperationRead, &varGuid, variableName)) {
+ if (!verifyPermission(kIONVRAMOperationRead, guid, name)) {
DEBUG_INFO("Not privileged\n");
goto exit;
}
- NVRAMLOCK();
- theObject.reset(dict->getObject(variableName), OSRetain);
+ NVRAMREADLOCK();
+ theObject.reset(dict->getObject(name), OSRetain);
NVRAMUNLOCK();
if (theObject != nullptr) {
return theObject;
}
+OSSharedPtr<OSObject>
+IODTNVRAM::copyProperty(const OSSymbol *aKey) const
+{
+ const char *variableName;
+ uuid_t varGuid;
+
+ if (skipKey(aKey)) {
+ return nullptr;
+ }
+ DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
+
+ parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
+
+ return copyPropertyWithGUIDAndName(&varGuid, variableName);
+}
+
OSSharedPtr<OSObject>
IODTNVRAM::copyProperty(const char *aKey) const
{
}
IOReturn
-IODTNVRAM::setPropertyInternal(const OSSymbol *aKey, OSObject *anObject)
+IODTNVRAM::setPropertyWithGUIDAndName(const uuid_t *guid, const char *name, OSObject *anObject)
{
- IOReturn result = kIOReturnSuccess;
+ IOReturn ret = kIOReturnSuccess;
bool remove = false;
OSString *tmpString = nullptr;
OSSharedPtr<OSObject> propObject, oldObject;
OSSharedPtr<OSObject> sharedObject(anObject, OSRetain);
- const char *variableName;
- uuid_t varGuid;
OSDictionary *dict;
bool deletePropertyKey, syncNowPropertyKey, forceSyncNowPropertyKey;
bool ok;
size_t propDataSize = 0;
- DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
-
- parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
- deletePropertyKey = strncmp(variableName, kIONVRAMDeletePropertyKey, sizeof(kIONVRAMDeletePropertyKey)) == 0;
- syncNowPropertyKey = strncmp(variableName, kIONVRAMSyncNowPropertyKey, sizeof(kIONVRAMSyncNowPropertyKey)) == 0;
- forceSyncNowPropertyKey = strncmp(variableName, kIONVRAMForceSyncNowPropertyKey, sizeof(kIONVRAMForceSyncNowPropertyKey)) == 0;
+ deletePropertyKey = strncmp(name, kIONVRAMDeletePropertyKey, sizeof(kIONVRAMDeletePropertyKey)) == 0;
+ syncNowPropertyKey = strncmp(name, kIONVRAMSyncNowPropertyKey, sizeof(kIONVRAMSyncNowPropertyKey)) == 0;
+ forceSyncNowPropertyKey = strncmp(name, kIONVRAMForceSyncNowPropertyKey, sizeof(kIONVRAMForceSyncNowPropertyKey)) == 0;
if (deletePropertyKey) {
tmpString = OSDynamicCast(OSString, anObject);
if (tmpString != nullptr) {
+ const char *variableName;
+ uuid_t varGuid;
+
DEBUG_INFO("kIONVRAMDeletePropertyKey found\n");
- OSSharedPtr<const OSSymbol> sharedKey = OSSymbol::withString(tmpString);
- removeProperty(sharedKey.get());
+
+ parseVariableName(tmpString->getCStringNoCopy(), &varGuid, &variableName);
+ removePropertyWithGUIDAndName(&varGuid, variableName);
} else {
DEBUG_INFO("kIONVRAMDeletePropertyKey value needs to be an OSString\n");
- result = kIOReturnError;
+ ret = kIOReturnError;
}
goto exit;
} else if (syncNowPropertyKey || forceSyncNowPropertyKey) {
tmpString = OSDynamicCast(OSString, anObject);
- DEBUG_INFO("NVRAM sync key %s found\n", aKey->getCStringNoCopy());
+ DEBUG_INFO("NVRAM sync key %s found\n", name);
if (tmpString != nullptr) {
// We still want to throttle NVRAM commit rate for SyncNow. ForceSyncNow is provided as a really big hammer.
syncInternal(syncNowPropertyKey);
} else {
- DEBUG_INFO("%s value needs to be an OSString\n", variableName);
- result = kIOReturnError;
+ DEBUG_INFO("%s value needs to be an OSString\n", name);
+ ret = kIOReturnError;
}
goto exit;
}
- result = chooseDictionary(kIONVRAMOperationWrite, &varGuid, variableName, &dict);
- if (result != kIOReturnSuccess) {
+ ret = chooseDictionary(kIONVRAMOperationWrite, guid, name, &dict);
+ if (ret != kIOReturnSuccess) {
+ DEBUG_INFO("No dictionary\n");
goto exit;
}
- if (!verifyPermission(kIONVRAMOperationWrite, &varGuid, variableName)) {
+ if (!verifyPermission(kIONVRAMOperationWrite, guid, name)) {
DEBUG_INFO("Not privileged\n");
- result = kIOReturnNotPrivileged;
+ ret = kIOReturnNotPrivileged;
goto exit;
}
// Make sure the object is of the correct type.
- switch (getVariableType(variableName)) {
+ switch (getVariableType(name)) {
case kOFVariableTypeBoolean:
propObject = OSDynamicPtrCast<OSBoolean>(sharedObject);
break;
if (propObject != nullptr) {
propDataSize = (OSDynamicPtrCast<OSString>(propObject))->getLength();
- if (aKey->isEqualTo(kIONVRAMBootArgsKey) && (propDataSize >= BOOT_LINE_LENGTH)) {
+ if ((strncmp(name, kIONVRAMBootArgsKey, sizeof(kIONVRAMBootArgsKey)) == 0) && (propDataSize >= BOOT_LINE_LENGTH)) {
DEBUG_ERROR("boot-args size too large for BOOT_LINE_LENGTH, propDataSize=%zu\n", propDataSize);
- result = kIOReturnNoSpace;
+ ret = kIOReturnNoSpace;
goto exit;
}
}
if (propObject == nullptr) {
DEBUG_INFO("No property object\n");
- result = kIOReturnBadArgument;
+ ret = kIOReturnBadArgument;
goto exit;
}
- if (!verifyWriteSizeLimit(&varGuid, variableName, propDataSize)) {
- DEBUG_ERROR("Property data size of %zu too long for %s\n", propDataSize, variableName);
- result = kIOReturnNoSpace;
+ if (!verifyWriteSizeLimit(guid, name, propDataSize)) {
+ DEBUG_ERROR("Property data size of %zu too long for %s\n", propDataSize, name);
+ ret = kIOReturnNoSpace;
goto exit;
}
- NVRAMLOCK();
- ok = handleSpecialVariables(variableName, &varGuid, propObject.get(), &result);
+ NVRAMWRITELOCK();
+ ok = handleSpecialVariables(name, guid, propObject.get(), &ret);
NVRAMUNLOCK();
if (ok) {
goto exit;
}
- NVRAMLOCK();
- oldObject.reset(dict->getObject(variableName), OSRetain);
+ NVRAMREADLOCK();
+ oldObject.reset(dict->getObject(name), OSRetain);
+ NVRAMUNLOCK();
+
if (remove == false) {
DEBUG_INFO("Adding object\n");
- if (!dict->setObject(variableName, propObject.get())) {
- result = kIOReturnBadArgument;
+ NVRAMWRITELOCK();
+ if (!dict->setObject(name, propObject.get())) {
+ ret = kIOReturnBadArgument;
}
+ NVRAMUNLOCK();
} else {
DEBUG_INFO("Removing object\n");
// Check for existence so we can decide whether we need to sync variables
if (oldObject) {
- result = removePropertyInternal(aKey);
+ ret = removePropertyWithGUIDAndName(guid, name);
} else {
- result = kIOReturnNotFound;
+ ret = kIOReturnNotFound;
}
}
- NVRAMUNLOCK();
- if (result == kIOReturnSuccess) {
- result = serializeVariables();
- if (result != kIOReturnSuccess) {
- DEBUG_ERROR("serializeVariables failed, result=0x%08x\n", result);
+ if (ret == kIOReturnSuccess) {
+ ret = serializeVariables();
+ if (ret != kIOReturnSuccess) {
+ DEBUG_ERROR("serializeVariables failed, ret=%#08x\n", ret);
- NVRAMLOCK();
+ NVRAMWRITELOCK();
if (oldObject) {
- dict->setObject(variableName, oldObject.get());
+ dict->setObject(name, oldObject.get());
} else {
- dict->removeObject(variableName);
+ dict->removeObject(name);
}
NVRAMUNLOCK();
(void) serializeVariables();
- result = kIOReturnNoMemory;
+ ret = kIOReturnNoMemory;
}
}
}
exit:
- DEBUG_INFO("result=0x%08x\n", result);
+ DEBUG_INFO("ret=%#08x\n", ret);
- return result;
+ return ret;
+}
+
+IOReturn
+IODTNVRAM::setPropertyInternal(const OSSymbol *aKey, OSObject *anObject)
+{
+ const char *variableName;
+ uuid_t varGuid;
+
+ DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
+
+ parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
+
+ return setPropertyWithGUIDAndName(&varGuid, variableName, anObject);
}
bool
{
IOReturn ret;
- NVRAMLOCK();
ret = removePropertyInternal(aKey);
- NVRAMUNLOCK();
if (ret == kIOReturnSuccess) {
serializeVariables();
} else {
- DEBUG_INFO("removePropertyInternal failed, ret=0x%08x\n", ret);
+ DEBUG_INFO("removePropertyInternal failed, ret=%#08x\n", ret);
}
}
IOReturn
-IODTNVRAM::removePropertyInternal(const OSSymbol *aKey)
+IODTNVRAM::removePropertyWithGUIDAndName(const uuid_t *guid, const char *name)
{
- IOReturn result;
- const char *variableName;
- uuid_t varGuid;
+ IOReturn ret;
OSDictionary *dict;
+ bool removed = false;
- DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
-
- NVRAMLOCKASSERT();
-
- parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
+ DEBUG_INFO("name=%s\n", name);
- result = chooseDictionary(kIONVRAMOperationDelete, &varGuid, variableName, &dict);
- if (result != kIOReturnSuccess) {
+ ret = chooseDictionary(kIONVRAMOperationDelete, guid, name, &dict);
+ if (ret != kIOReturnSuccess) {
+ DEBUG_INFO("No dictionary\n");
goto exit;
}
- if (!verifyPermission(kIONVRAMOperationDelete, &varGuid, variableName)) {
+ if (!verifyPermission(kIONVRAMOperationDelete, guid, name)) {
DEBUG_INFO("Not priveleged\n");
- result = kIOReturnNotPrivileged;
+ ret = kIOReturnNotPrivileged;
goto exit;
}
+ NVRAMWRITELOCK();
+
// If the object exists, remove it from the dictionary.
- if (dict->getObject(variableName) != nullptr) {
- dict->removeObject(variableName);
+ if (dict->getObject(name) != nullptr) {
+ dict->removeObject(name);
+ removed = true;
+ } else {
+ DEBUG_INFO("%s not found\n", name);
+ }
+
+ NVRAMUNLOCK();
+
+ if (removed) {
+ ret = serializeVariables();
+ DEBUG_INFO("serializeVariables ret=0x%08x\n", ret);
}
exit:
- return result;
+ return ret;
+}
+
+IOReturn
+IODTNVRAM::removePropertyInternal(const OSSymbol *aKey)
+{
+ IOReturn ret;
+ const char *variableName;
+ uuid_t varGuid;
+
+ DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
+
+ parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
+
+ ret = removePropertyWithGUIDAndName(&varGuid, variableName);
+
+ return ret;
}
IOReturn
IODTNVRAM::setProperties(OSObject *properties)
{
- IOReturn result = kIOReturnSuccess;
+ IOReturn ret = kIOReturnSuccess;
OSObject *object;
const OSSymbol *key;
OSDictionary *dict;
return kIOReturnBadArgument;
}
- while (result == kIOReturnSuccess) {
+ while (ret == kIOReturnSuccess) {
key = OSDynamicCast(OSSymbol, iter->getNextObject());
if (key == nullptr) {
break;
continue;
}
- result = setPropertyInternal(key, object);
+ ret = setPropertyInternal(key, object);
}
- DEBUG_INFO("result=0x%08x\n", result);
+ DEBUG_INFO("ret=%#08x\n", ret);
- return result;
+ return ret;
}
IOReturn
OSSharedPtr<const OSSymbol> propSymbol;
OSSharedPtr<OSObject> propObject;
NVRAMRegionInfo *currentRegion;
- NVRAMRegionInfo variableRegions[] = { { NVRAM_CHRP_PARTITION_NAME_COMMON, _commonPartitionOffset, _commonPartitionSize, _commonDict, _commonImage},
- { NVRAM_CHRP_PARTITION_NAME_SYSTEM, _systemPartitionOffset, _systemPartitionSize, _systemDict, _systemImage} };
+ NVRAMRegionInfo variableRegions[] = { { kIONVRAMPartitionCommon, _commonPartitionOffset, _commonPartitionSize, _commonDict, _commonImage},
+ { kIONVRAMPartitionSystem, _systemPartitionOffset, _systemPartitionSize, _systemDict, _systemImage} };
DEBUG_INFO("...\n");
currentRegion->dict = OSDictionary::withCapacity(1);
- DEBUG_INFO("region = %s\n", currentRegion->name);
+ DEBUG_INFO("region = %d\n", currentRegion->type);
cnt = 0;
while (cnt < currentRegion->size) {
// Break if there is no name.
}
// Create the boot-args property if it is not in the dictionary.
- if (_commonDict->getObject(kIONVRAMBootArgsKey) == nullptr) {
- propObject = OSString::withCStringNoCopy("");
- if (propObject != nullptr) {
- _commonDict->setObject(kIONVRAMBootArgsKey, propObject.get());
+ if (_systemDict != nullptr) {
+ if (_systemDict->getObject(kIONVRAMBootArgsKey) == nullptr) {
+ propObject = OSString::withCStringNoCopy("");
+ if (propObject != nullptr) {
+ _systemDict->setObject(kIONVRAMBootArgsKey, propObject.get());
+ }
+ }
+ } else if (_commonDict != nullptr) {
+ if (_commonDict->getObject(kIONVRAMBootArgsKey) == nullptr) {
+ propObject = OSString::withCStringNoCopy("");
+ if (propObject != nullptr) {
+ _commonDict->setObject(kIONVRAMBootArgsKey, propObject.get());
+ }
}
}
- DEBUG_INFO("%s _commonDict=%p _systemDict=%p\n", __FUNCTION__, _commonDict.get(), _systemDict.get());
+ DEBUG_INFO("%s _commonDict=%p _systemDict=%p\n", __FUNCTION__, _commonDict ? _commonDict.get() : nullptr, _systemDict ? _systemDict.get() : nullptr);
return kIOReturnSuccess;
}
UInt32 commonUsed = 0;
OSSharedPtr<OSData> nvramImage;
NVRAMRegionInfo *currentRegion;
- NVRAMRegionInfo variableRegions[] = { { NVRAM_CHRP_PARTITION_NAME_COMMON, _commonPartitionOffset, _commonPartitionSize, _commonDict, _commonImage},
- { NVRAM_CHRP_PARTITION_NAME_SYSTEM, _systemPartitionOffset, _systemPartitionSize, _systemDict, _systemImage} };
+ NVRAMRegionInfo variableRegions[] = { { kIONVRAMPartitionCommon, _commonPartitionOffset, _commonPartitionSize, _commonDict, _commonImage},
+ { kIONVRAMPartitionSystem, _systemPartitionOffset, _systemPartitionSize, _systemDict, _systemImage} };
if (_systemPanicked) {
return kIOReturnNotReady;
DEBUG_INFO("...\n");
- NVRAMLOCK();
+ NVRAMREADLOCK();
for (regionIndex = 0; regionIndex < ARRAY_SIZE(variableRegions); regionIndex++) {
currentRegion = &variableRegions[regionIndex];
continue;
}
- DEBUG_INFO("region = %s\n", currentRegion->name);
+ DEBUG_INFO("region = %d\n", currentRegion->type);
buffer = tmpBuffer = IONew(UInt8, currentRegion->size);
if (buffer == nullptr) {
- return kIOReturnNoMemory;
+ ok = false;
+ ret = kIOReturnNoMemory;
+ break;
}
bzero(buffer, currentRegion->size);
IODelete(buffer, UInt8, currentRegion->size);
- if ((strncmp(currentRegion->name, NVRAM_CHRP_PARTITION_NAME_SYSTEM, strlen(NVRAM_CHRP_PARTITION_NAME_SYSTEM)) == 0) &&
+ if ((currentRegion->type == kIONVRAMPartitionSystem) &&
(_systemService != nullptr)) {
- _systemService->setProperties(_systemDict.get());
- systemUsed = maxLength;
- } else if ((strncmp(currentRegion->name, NVRAM_CHRP_PARTITION_NAME_COMMON, strlen(NVRAM_CHRP_PARTITION_NAME_COMMON)) == 0) &&
+ _systemService->setVariables(_systemDict.get());
+ systemUsed = (uint32_t)(tmpBuffer - buffer);
+ } else if ((currentRegion->type == kIONVRAMPartitionCommon) &&
(_commonService != nullptr)) {
- _commonService->setProperties(_commonDict.get());
- commonUsed = maxLength;
+ _commonService->setVariables(_commonDict.get());
+ commonUsed = (uint32_t)(tmpBuffer - buffer);
}
if (!ok) {
- return kIOReturnBadArgument;
+ ret = kIOReturnBadArgument;
+ break;
}
}
- nvramImage = OSData::withBytes(_nvramImage, _nvramSize);
-
NVRAMUNLOCK();
DEBUG_INFO("ok=%d\n", ok);
- CONTROLLERLOCK();
+ if (ok) {
+ nvramImage = OSData::withBytes(_nvramImage, _nvramSize);
+ CONTROLLERLOCK();
- if (_systemService) {
- sizeUsed = OSNumber::withNumber(systemUsed, 32);
- _nvramController->setProperty("SystemUsed", sizeUsed.get());
- sizeUsed.reset();
- }
+ if (_systemService) {
+ sizeUsed = OSNumber::withNumber(systemUsed, 32);
+ _nvramController->setProperty("SystemUsed", sizeUsed.get());
+ DEBUG_INFO("SystemUsed=%u\n", (unsigned int)commonUsed);
+ sizeUsed.reset();
+ }
- if (_commonService) {
- sizeUsed = OSNumber::withNumber(commonUsed, 32);
- _nvramController->setProperty("CommonUsed", sizeUsed.get());
- sizeUsed.reset();
- }
+ if (_commonService) {
+ sizeUsed = OSNumber::withNumber(commonUsed, 32);
+ _nvramController->setProperty("CommonUsed", sizeUsed.get());
+ DEBUG_INFO("CommonUsed=%u\n", (unsigned int)commonUsed);
+ sizeUsed.reset();
+ }
- ret = _nvramController->write(0, (uint8_t *)nvramImage->getBytesNoCopy(), nvramImage->getLength());
+ ret = _nvramController->write(0, (uint8_t *)nvramImage->getBytesNoCopy(), nvramImage->getLength());
- CONTROLLERUNLOCK();
+ CONTROLLERUNLOCK();
+ }
return ret;
}
{
const OSSymbol* propSymbolRaw = nullptr;
OSObject* propObjectRaw = nullptr;
- bool result = convertPropToObject(propName, propNameLength, propData, propDataLength,
+ bool ok = convertPropToObject(propName, propNameLength, propData, propDataLength,
&propSymbolRaw, &propObjectRaw);
propSymbol.reset(propSymbolRaw, OSNoRetain);
propObject.reset(propObjectRaw, OSNoRetain);
- return result;
+ return ok;
}
bool
} else if (tmpValue < 1000) {
snprintf((char *)buffer, remaining, "%d", (uint32_t)tmpValue);
} else {
- snprintf((char *)buffer, remaining, "0x%x", (uint32_t)tmpValue);
+ snprintf((char *)buffer, remaining, "%#x", (uint32_t)tmpValue);
}
}
break;
UInt32 resultValueLen = 0;
UInt8 byte;
- NVRAMLOCK();
+ NVRAMREADLOCK();
data = OSDynamicCast(OSData, _commonDict->getObject(_registryPropertiesKey.get()));
NVRAMUNLOCK();
// copy over existing properties for other entries
- NVRAMLOCK();
+ NVRAMWRITELOCK();
oldData.reset(OSDynamicCast(OSData, _commonDict->getObject(_registryPropertiesKey.get())), OSRetain);
if (oldData) {
if (ok) {
if (serializeVariables() != kIOReturnSuccess) {
- NVRAMLOCK();
+ NVRAMWRITELOCK();
if (oldData) {
_commonDict->setObject(_registryPropertiesKey.get(), oldData.get());
} else {