Loading...
--- xnu/xnu-12377.121.6/iokit/Kernel/IONVRAM.cpp
+++ xnu/xnu-8796.121.2/iokit/Kernel/IONVRAM.cpp
@@ -39,7 +39,6 @@
#include <IOKit/IOBSD.h>
#include <kern/debug.h>
#include <os/system_event_log.h>
-#include <pexpert/boot.h>
#include <sys/csr.h>
#define super IOService
@@ -53,10 +52,9 @@
#define MAX_VAR_NAME_SIZE 63
-#define kNVRAMBankSizeKey "nvram-bank-size"
-#define kNVRAMBankCountKey "nvram-bank-count"
-#define kNVRAMCurrentBankKey "nvram-current-bank"
-#define kNVRAMClearTestVarKey "clear-test-vars"
+#define kNVRAMBankSizeKey "nvram-bank-size"
+#define kNVRAMBankCountKey "nvram-bank-count"
+#define kNVRAMCurrentBankKey "nvram-current-bank"
#define kCurrentGenerationCountKey "Generation"
#define kCurrentNVRAMVersionKey "Version"
@@ -67,32 +65,17 @@
#define kIONVRAMPrivilege kIOClientPrivilegeAdministrator
#define MIN_SYNC_NOW_INTERVAL 15*60 /* Minimum 15 Minutes interval mandated */
-
-enum IONVRAMLogging {
- kIONVRAMNoLogs = 0,
- kIONVRAMInfoLogs = 1,
- kIONVRAMErrorLogs = 2,
- kIONVRAMDataHexDump = 4
-};
-
-#define IS_LOG_BIT_SET(level) ((gNVRAMLogging & (level)) != 0)
#if defined(DEBUG) || defined(DEVELOPMENT)
#define DEBUG_IFERROR(err, fmt, args...) \
({ \
- if ((err != kIOReturnSuccess) || IS_LOG_BIT_SET(kIONVRAMErrorLogs)) \
+ if ((err != kIOReturnSuccess) || gNVRAMLogging) \
IOLog("%s:%s:%u - " fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##args); \
})
-#define DEBUG_INFO_IF(log, fmt, args...) \
-({ \
- if ((log) && IS_LOG_BIT_SET(kIONVRAMInfoLogs)) \
- IOLog("%s:%s:%u - " fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##args); \
-})
-
#define DEBUG_INFO(fmt, args...) \
({ \
- if (IS_LOG_BIT_SET(kIONVRAMInfoLogs)) \
+ if (gNVRAMLogging) \
IOLog("%s:%s:%u - " fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##args); \
})
@@ -104,77 +87,55 @@
#define DEBUG_IFERROR(err, fmt, args...) (void)NULL
#define DEBUG_INFO(fmt, args...) (void)NULL
#define DEBUG_ALWAYS(fmt, args...) (void)NULL
-#define DEBUG_INFO_IF(fmt, args...) (void)NULL
#endif
#define DEBUG_ERROR DEBUG_ALWAYS
#define SAFE_TO_LOCK() (preemption_enabled() && !panic_active())
-#define NVRAMLOCK(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IOLockLock(lock); \
+#define CONTROLLERLOCK() \
+({ \
+ if (SAFE_TO_LOCK()) \
+ IOLockLock(_controllerLock); \
})
-#define NVRAMUNLOCK(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IOLockUnlock(lock); \
+#define CONTROLLERUNLOCK() \
+({ \
+ if (SAFE_TO_LOCK()) \
+ IOLockUnlock(_controllerLock); \
})
-#define NVRAMLOCKASSERTHELD(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IOLockAssert(lock, kIOLockAssertOwned); \
+#define NVRAMREADLOCK() \
+({ \
+ if (SAFE_TO_LOCK()) \
+ IORWLockRead(_variableLock); \
})
-#define NVRAMREADLOCK(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IORWLockRead(lock); \
+#define NVRAMWRITELOCK() \
+({ \
+ if (SAFE_TO_LOCK()) \
+ IORWLockWrite(_variableLock); \
})
-#define NVRAMWRITELOCK(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IORWLockWrite(lock); \
+#define NVRAMUNLOCK() \
+({ \
+ if (SAFE_TO_LOCK()) \
+ IORWLockUnlock(_variableLock); \
})
-#define NVRAMRWUNLOCK(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IORWLockUnlock(lock); \
+#define NVRAMLOCKASSERTHELD() \
+({ \
+ if (SAFE_TO_LOCK()) \
+ IORWLockAssert(_variableLock, kIORWLockAssertHeld); \
})
-#define NVRAMRWUNLOCKANDWRITE(lock) \
-({ \
- NVRAMRWUNLOCK(lock); \
- NVRAMWRITELOCK(lock); \
+#define NVRAMLOCKASSERTEXCLUSIVE() \
+({ \
+ if (SAFE_TO_LOCK()) \
+ IORWLockAssert(_variableLock, kIORWLockAssertWrite); \
})
-#define NVRAMRWLOCKASSERTHELD(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IORWLockAssert(lock, kIORWLockAssertHeld); \
-})
-
-#define NVRAMRWLOCKASSERTEXCLUSIVE(lock) \
-({ \
- if (SAFE_TO_LOCK()) \
- IORWLockAssert(lock, kIORWLockAssertWrite); \
-})
-
-// MOD = Write, Delete
-// RST = Reset, Obliterate
-// RD = Read
-// DEL = Delete
-#define OP_RD ((1 << kIONVRAMOperationRead))
-#define OP_RST ((1 << kIONVRAMOperationObliterate) | (1 << kIONVRAMOperationReset))
-#define OP_DEL ((1 << kIONVRAMOperationDelete))
-#define OP_MOD ((1 << kIONVRAMOperationWrite) | OP_DEL)
-#define OP_MOD_RD (OP_RD | OP_MOD)
-#define OP_MOD_RST (OP_MOD | OP_RST)
+#define ENTITLED_MODIFY_ONLY ((1 << kIONVRAMOperationWrite) | (1 << kIONVRAMOperationDelete) | (1 << kIONVRAMOperationObliterate) | (1 << kIONVRAMOperationReset))
enum NVRAMVersion {
kNVRAMVersionUnknown,
@@ -192,28 +153,11 @@
// 7C436110-AB2A-4BBB-A880-FE41995C9F82
UUID_DEFINE(gAppleNVRAMGuid, 0x7C, 0x43, 0x61, 0x10, 0xAB, 0x2A, 0x4B, 0xBB, 0xA8, 0x80, 0xFE, 0x41, 0x99, 0x5C, 0x9F, 0x82);
-// Wifi NVRAM namespace
-// 36C28AB5-6566-4C50-9EBD-CBB920F83843
-UUID_DEFINE(gAppleWifiGuid, 0x36, 0xC2, 0x8A, 0xB5, 0x65, 0x66, 0x4C, 0x50, 0x9E, 0xBD, 0xCB, 0xB9, 0x20, 0xF8, 0x38, 0x43);
-
-// Prefix for kernel-only variables
-#define KERNEL_ONLY_VAR_NAME_PREFIX "krn."
-
-static TUNABLE(uint8_t, gNVRAMLogging, "nvram-log", kIONVRAMNoLogs);
-static TUNABLE(bool, gRestoreBoot, "-restore", false);
+static TUNABLE(bool, gNVRAMLogging, "nvram-log", false);
static bool gInternalBuild = false;
-
-// IONVRAMSystemVariableListInternal:
-// Used for internal builds only
-// "force-lock-bits" used by fwam over ssh nvram to device so they are unable to use entitlements
-// "stress-rack" used in SEG stress-rack restore prdocs
-#define IONVRAMSystemVariableListInternal IONVRAMSystemVariableList, \
- "force-lock-bits", \
- "stress-rack"
// allowlist variables from macboot that need to be set/get from system region if present
static const char * const gNVRAMSystemList[] = { IONVRAMSystemVariableList, nullptr };
-static const char * const gNVRAMSystemListInternal[] = { IONVRAMSystemVariableListInternal, nullptr };
typedef struct {
const char *name;
@@ -243,7 +187,6 @@
{"input-device", kOFVariableTypeString},
{"input-device-1", kOFVariableTypeString},
{"little-endian?", kOFVariableTypeBoolean},
- {"ldm", kOFVariableTypeBoolean},
{"load-base", kOFVariableTypeNumber},
{"mouse-device", kOFVariableTypeString},
{"nvramrc", kOFVariableTypeString},
@@ -266,11 +209,7 @@
{"use-nvramrc?", kOFVariableTypeBoolean},
{"virt-base", kOFVariableTypeNumber},
{"virt-size", kOFVariableTypeNumber},
- // Variables used for testing
- {"test-bool", kOFVariableTypeBoolean},
- {"test-num", kOFVariableTypeNumber},
- {"test-str", kOFVariableTypeString},
- {"test-data", kOFVariableTypeData},
+
#if !defined(__x86_64__)
{"acc-cm-override-charger-count", kOFVariableTypeNumber},
{"acc-cm-override-count", kOFVariableTypeNumber},
@@ -291,9 +230,6 @@
uint64_t NeverAllowedToDelete :1;
uint64_t SystemReadHidden :1;
uint64_t FullAccess :1;
- uint64_t InternalOnly :1;
- uint64_t TestingOnly :1;
- uint64_t RestoreModifyOnly :1;
uint64_t Reserved:57;
} Bits;
uint64_t Uint64;
@@ -311,7 +247,6 @@
.p.Bits.NeverAllowedToDelete = 1},
{"boot-image", .p.Bits.UserWrite = 1},
{"com.apple.System.fp-state", .p.Bits.KernelOnly = 1},
- {"enable-ephdm", .p.Bits.RestoreModifyOnly = 1},
{"fm-account-masked", .p.Bits.RootRequired = 1,
.p.Bits.NeverAllowedToDelete = 1},
{"fm-activation-locked", .p.Bits.RootRequired = 1,
@@ -331,26 +266,18 @@
{"acc-mb-ld-lifetime", .p.Bits.KernelOnly = 1},
{"backlight-level", .p.Bits.UserWrite = 1},
{"backlight-nits", .p.Bits.UserWrite = 1},
- {"ldm", .p.Bits.KernelOnly = 1},
{"com.apple.System.boot-nonce", .p.Bits.KernelOnly = 1},
{"com.apple.System.sep.art", .p.Bits.KernelOnly = 1},
{"darkboot", .p.Bits.UserWrite = 1},
{"nonce-seeds", .p.Bits.KernelOnly = 1},
#endif /* !defined(__x86_64__) */
// Variables used for testing permissions
- {"testSysReadHidden", .p.Bits.SystemReadHidden = 1,
- .p.Bits.TestingOnly = 1},
- {"testKernelOnly", .p.Bits.KernelOnly = 1,
- .p.Bits.TestingOnly = 1},
- {"testResetOnlyDel", .p.Bits.ResetNVRAMOnlyDelete = 1,
- .p.Bits.TestingOnly = 1},
- {"testNeverDel", .p.Bits.NeverAllowedToDelete = 1,
- .p.Bits.TestingOnly = 1},
- {"testUserWrite", .p.Bits.UserWrite = 1,
- .p.Bits.TestingOnly = 1},
- {"testRootReq", .p.Bits.RootRequired = 1,
- .p.Bits.TestingOnly = 1},
- {"reclaim-int", .p.Bits.InternalOnly = 1},
+ {"testSysReadHidden", .p.Bits.SystemReadHidden = 1},
+ {"testKernelOnly", .p.Bits.KernelOnly = 1},
+ {"testResetOnlyDel", .p.Bits.ResetNVRAMOnlyDelete = 1},
+ {"testNeverDel", .p.Bits.NeverAllowedToDelete = 1},
+ {"testUserWrite", .p.Bits.UserWrite = 1},
+ {"testRootReq", .p.Bits.RootRequired = 1},
{nullptr, {.Bits.FullAccess = 1}} // Default access
};
@@ -364,34 +291,9 @@
// variable-guid pair entries that require entitlement check to do specified nvram operations
static const
VariableEntitlementEntry gVariableEntitlements[] = {
- {OP_MOD_RST, &gAppleNVRAMGuid, "ownership-warning", "com.apple.private.iokit.ddl-write"},
- {OP_MOD, &gAppleSystemVariableGuid, "BluetoothInfo", "com.apple.private.iokit.nvram-bluetooth"},
- {OP_MOD, &gAppleSystemVariableGuid, "BluetoothUHEDevices", "com.apple.private.iokit.nvram-bluetooth"},
- {OP_MOD, &gAppleNVRAMGuid, "bluetoothExternalDongleFailed", "com.apple.private.iokit.nvram-bluetooth"},
- {OP_MOD, &gAppleNVRAMGuid, "bluetoothInternalControllerInfo", "com.apple.private.iokit.nvram-bluetooth"},
- {OP_RD, &gAppleSystemVariableGuid, "current-network", "com.apple.private.security.nvram.wifi-psks"},
- {OP_RD, &gAppleWifiGuid, "current-network", "com.apple.private.security.nvram.wifi-psks"},
- {OP_RD, &gAppleSystemVariableGuid, "preferred-networks", "com.apple.private.security.nvram.wifi-psks"},
- {OP_RD, &gAppleWifiGuid, "preferred-networks", "com.apple.private.security.nvram.wifi-psks"},
- {OP_RD, &gAppleSystemVariableGuid, "preferred-count", "com.apple.private.security.nvram.wifi-psks"},
- {OP_RD, &gAppleWifiGuid, "preferred-count", "com.apple.private.security.nvram.wifi-psks"},
- {OP_MOD_RD, &gAppleSystemVariableGuid, "fmm-mobileme-token-FMM", "com.apple.private.security.nvram.fmm"},
- {OP_MOD_RD, &gAppleNVRAMGuid, "fmm-mobileme-token-FMM", "com.apple.private.security.nvram.fmm"},
- {OP_MOD_RD, &gAppleSystemVariableGuid, "fmm-mobileme-token-FMM-BridgeHasAccount", "com.apple.private.security.nvram.fmm"},
- {OP_MOD_RD, &gAppleNVRAMGuid, "fmm-mobileme-token-FMM-BridgeHasAccount", "com.apple.private.security.nvram.fmm"},
- {OP_MOD_RD, &gAppleSystemVariableGuid, "fmm-computer-name", "com.apple.private.security.nvram.fmm"},
- {OP_MOD_RD, &gAppleNVRAMGuid, "fmm-computer-name", "com.apple.private.security.nvram.fmm"},
- {OP_MOD, &gAppleSystemVariableGuid, "rdma-enable", "com.apple.private.iokit.rdma"},
- {OP_MOD, &gAppleNVRAMGuid, "rdma-enable", "com.apple.private.iokit.rdma"},
- // Variables used for testing entitlement
- {OP_MOD_RST, &gAppleNVRAMGuid, "testEntModRst", "com.apple.private.iokit.testEntModRst"},
- {OP_MOD_RST, &gAppleSystemVariableGuid, "testEntModRstSys", "com.apple.private.iokit.testEntModRst"},
- {OP_RST, &gAppleNVRAMGuid, "testEntRst", "com.apple.private.iokit.testEntRst"},
- {OP_RST, &gAppleSystemVariableGuid, "testEntRstSys", "com.apple.private.iokit.testEntRst"},
- {OP_RD, &gAppleNVRAMGuid, "testEntRd", "com.apple.private.iokit.testEntRd"},
- {OP_RD, &gAppleSystemVariableGuid, "testEntRdSys", "com.apple.private.iokit.testEntRd"},
- {OP_DEL, &gAppleNVRAMGuid, "testEntDel", "com.apple.private.iokit.testEntDel"},
- {OP_DEL, &gAppleSystemVariableGuid, "testEntDelSys", "com.apple.private.iokit.testEntDel"},
+ {ENTITLED_MODIFY_ONLY, &gAppleNVRAMGuid, "ownership-warning", "com.apple.private.iokit.ddl-write"},
+ // Variable used for testing entitlement
+ {ENTITLED_MODIFY_ONLY, &gAppleNVRAMGuid, "testEntitlement", "com.apple.private.iokit.testentitlement"},
{0, &UUID_NULL, nullptr, nullptr}
};
@@ -447,10 +349,9 @@
variableInAllowList(const char *varName)
{
unsigned int i = 0;
- const char * const *list = gInternalBuild ? gNVRAMSystemListInternal : gNVRAMSystemList;
-
- while (list[i] != nullptr) {
- if (strcmp(varName, list[i]) == 0) {
+
+ while (gNVRAMSystemList[i] != nullptr) {
+ if (strcmp(varName, gNVRAMSystemList[i]) == 0) {
return true;
}
i++;
@@ -463,7 +364,11 @@
verifyWriteSizeLimit(const uuid_t varGuid, const char *variableName, size_t propDataSize)
{
if (variableInAllowList(variableName)) {
- return propDataSize <= BOOT_LINE_LENGTH;
+ if (strnstr(variableName, "breadcrumbs", strlen(variableName)) != NULL) {
+ return propDataSize <= 1024;
+ } else {
+ return propDataSize <= 768;
+ }
}
return true;
@@ -544,7 +449,7 @@
* @param systemActive boolean to indicate if it has system partition size > 0
*/
static void
-translateGUID(const uuid_t varGuid, const char *variableName, uuid_t destGuid, bool systemActive, bool log)
+translateGUID(const uuid_t varGuid, const char *variableName, uuid_t destGuid, bool systemActive)
{
if (varGuid == nullptr || variableName == nullptr || destGuid == nullptr) {
DEBUG_ERROR("nullptr passed as an argument\n");
@@ -555,20 +460,23 @@
if (systemActive) {
if (variableInAllowList(variableName)) {
- DEBUG_INFO_IF(log, "Using system GUID due to allow list\n");
+ if (!systemGuid) {
+ DEBUG_ERROR("System GUID not supplied for %s\n", variableName);
+ }
+ DEBUG_INFO("Using system GUID due to allow list\n");
uuid_copy(destGuid, gAppleSystemVariableGuid);
} else if (systemGuid) {
- DEBUG_INFO_IF(log, "System GUID used\n");
+ DEBUG_INFO("System GUID used\n");
uuid_copy(destGuid, gAppleSystemVariableGuid);
} else {
- DEBUG_INFO_IF(log, "Use given guid\n");
+ DEBUG_INFO("Use given guid\n");
uuid_copy(destGuid, varGuid);
}
} else if (systemGuid) {
- DEBUG_INFO_IF(log, "Overriding to Apple guid\n");
+ DEBUG_INFO("Overriding to Apple guid\n");
uuid_copy(destGuid, gAppleNVRAMGuid);
} else {
- DEBUG_INFO_IF(log, "Use given guid\n");
+ DEBUG_INFO("Use given guid\n");
uuid_copy(destGuid, varGuid);
}
}
@@ -588,7 +496,7 @@
* @return false if varName/varGuid/veChecked was NULL or if entitlement check returned false
*/
static bool
-verifyVarEntitlement(const uuid_t varGuid, const char *varName, IONVRAMOperation op, bool systemActive, bool *veChecked, bool log)
+verifyVarEntitlement(const uuid_t varGuid, const char *varName, IONVRAMOperation op, bool systemActive, bool *veChecked)
{
if (varGuid == nullptr || varName == nullptr || veChecked == nullptr) {
DEBUG_ERROR("nullptr passed as an argument\n");
@@ -599,15 +507,13 @@
const VariableEntitlementEntry *entry;
*veChecked = false;
- translateGUID(varGuid, varName, translatedGuid, systemActive, log);
-
entry = gVariableEntitlements;
while ((entry != nullptr) && (entry->varName != nullptr)) {
+ translateGUID(varGuid, varName, translatedGuid, systemActive);
if ((strcmp(entry->varName, varName) == 0) && (uuid_compare(translatedGuid, *(entry->varGuid)) == 0)) {
// check if task entitlement check is required for this operation
if (entry->checkOp & (1 << op)) {
*veChecked = true;
- DEBUG_INFO_IF(log, "Checking entitlement %s for %s for operation %s\n", entry->varEntitlement, varName, getNVRAMOpString(op));
return IOCurrentTaskHasEntitlement(entry->varEntitlement);
}
break;
@@ -619,44 +525,24 @@
}
static bool
-kernelOnlyVar(const char *varName)
-{
- if (strncmp(varName, KERNEL_ONLY_VAR_NAME_PREFIX, sizeof(KERNEL_ONLY_VAR_NAME_PREFIX) - 1) == 0) {
- return true;
- }
-
- return false;
-}
-
-static bool
-verifyPermission(IONVRAMOperation op, const uuid_t varGuid, const char *varName, const bool systemActive, bool log)
+verifyPermission(IONVRAMOperation op, const uuid_t varGuid, const char *varName, const bool systemActive)
{
VariablePermission perm;
bool kernel, varEntitled, writeEntitled = false, readEntitled = false, allowList, systemGuid = false, systemEntitled = false, systemInternalEntitled = false, systemAllow, systemReadHiddenAllow = false;
bool admin = false;
bool ok = false;
- if (verifyVarEntitlement(varGuid, varName, op, systemActive, &varEntitled, log) == false) {
+ if (verifyVarEntitlement(varGuid, varName, op, systemActive, &varEntitled) == false) {
goto exit;
}
perm = getVariablePermission(varName);
kernel = current_task() == kernel_task;
- if (perm.Bits.KernelOnly || kernelOnlyVar(varName)) {
- DEBUG_INFO_IF(log, "KernelOnly access for %s, kernel=%d\n", varName, kernel);
+
+ if (perm.Bits.KernelOnly) {
+ DEBUG_INFO("KernelOnly access for %s, kernel=%d\n", varName, kernel);
ok = kernel;
- goto exit;
- }
-
- if (perm.Bits.RestoreModifyOnly && (OP_MOD & (1 << op))) {
- DEBUG_INFO_IF(log, "RestoreModifyOnly access for %s, gRestoreBoot=%d\n", varName, gRestoreBoot);
- ok = gRestoreBoot;
- goto exit;
- }
-
- if (perm.Bits.InternalOnly && !gInternalBuild) {
- DEBUG_INFO_IF(log, "InternalOnly access for %s, gInternalBuild=%d\n", varName, gInternalBuild);
goto exit;
}
@@ -675,7 +561,7 @@
case kIONVRAMOperationRead:
if (systemGuid && perm.Bits.SystemReadHidden) {
ok = systemReadHiddenAllow;
- } else if (kernel || admin || readEntitled || perm.Bits.FullAccess || varEntitled) {
+ } else if (kernel || admin || readEntitled || perm.Bits.FullAccess) {
ok = true;
}
break;
@@ -687,8 +573,6 @@
if (!systemAllow) {
DEBUG_ERROR("Allowed write to system region when NOT entitled for %s\n", varName);
}
- } else if (varEntitled) {
- DEBUG_INFO_IF(log, "Allowed write to system region using variable specific entitlement for %s\n", varName);
} else if (!systemAllow) {
DEBUG_ERROR("Not entitled for system region writes for %s\n", varName);
break;
@@ -702,13 +586,13 @@
case kIONVRAMOperationObliterate:
case kIONVRAMOperationReset:
if (perm.Bits.NeverAllowedToDelete) {
- DEBUG_INFO_IF(log, "Never allowed to delete %s\n", varName);
+ DEBUG_INFO("Never allowed to delete %s\n", varName);
break;
} else if ((op == kIONVRAMOperationObliterate) && perm.Bits.ResetNVRAMOnlyDelete) {
- DEBUG_INFO_IF(log, "Not allowed to obliterate %s\n", varName);
+ DEBUG_INFO("Not allowed to obliterate %s\n", varName);
break;
} else if ((op == kIONVRAMOperationDelete) && perm.Bits.ResetNVRAMOnlyDelete) {
- DEBUG_INFO_IF(log, "Only allowed to delete %s via NVRAM reset\n", varName);
+ DEBUG_INFO("Only allowed to delete %s via NVRAM reset\n", varName);
break;
}
@@ -718,8 +602,6 @@
if (!systemAllow) {
DEBUG_ERROR("Allowed delete to system region when NOT entitled for %s\n", varName);
}
- } else if (varEntitled) {
- DEBUG_INFO_IF(log, "Allowed delete to system region using variable specific entitlement for %s\n", varName);
} else if (!systemAllow) {
DEBUG_ERROR("Not entitled for system region deletes for %s\n", varName);
break;
@@ -734,8 +616,8 @@
}
exit:
- DEBUG_INFO_IF(log, "Permission for %s of %s %s: I=%d R=%d kern=%d, adm=%d, wE=%d, rE=%d, sG=%d, sEd=%d, sIEd=%d, sRHA=%d, UW=%d, vE=%d\n", getNVRAMOpString(op), varName, ok ? "granted" : "denied",
- gInternalBuild, gRestoreBoot, kernel, admin, writeEntitled, readEntitled, systemGuid, systemEntitled, systemInternalEntitled, systemReadHiddenAllow, perm.Bits.UserWrite, varEntitled);
+ DEBUG_INFO("Permission for %s of %s %s: kern=%d, adm=%d, wE=%d, rE=%d, sG=%d, sEd=%d, sIEd=%d, sRHA=%d, UW=%d, vE=%d\n", getNVRAMOpString(op), varName, ok ? "granted" : "denied",
+ kernel, admin, writeEntitled, readEntitled, systemGuid, systemEntitled, systemInternalEntitled, systemReadHiddenAllow, perm.Bits.UserWrite, varEntitled);
return ok;
}
@@ -748,7 +630,7 @@
parseVariableName(canonicalKey->getCStringNoCopy(), &varGuid, &varName);
- return verifyPermission(op, varGuid, varName, systemActive, true);
+ return verifyPermission(op, varGuid, varName, systemActive);
}
static bool
@@ -763,9 +645,7 @@
aKey->isEqualTo(kIOBSDMinorKey) ||
aKey->isEqualTo(kIOBSDUnitKey) ||
aKey->isEqualTo(kIOUserServicePropertiesKey) ||
- aKey->isEqualTo(kIOExclaveAssignedKey) ||
- aKey->isEqualTo(kIOMatchCategoryKey) ||
- aKey->isEqualTo(kIOBusyInterest);
+ aKey->isEqualTo(kIOMatchCategoryKey);
}
static OSSharedPtr<const OSSymbol>
@@ -777,7 +657,7 @@
length = sizeof(uuid_string_t) - 1 + sizeof(':') + strlen(cstring) + 1;
- canonicalString = (char *) IOMallocZeroData(length);
+ canonicalString = (char *) IOMallocData(length);
if (canonicalString == nullptr) {
return NULL;
}
@@ -794,69 +674,27 @@
}
static void
-dumpDict(OSSharedPtr<OSDictionary> dict)
+dumpDict(const OSDictionary *dict)
{
const OSSymbol *key;
OSSharedPtr<OSCollectionIterator> iter;
unsigned int count = 0;
- iter = OSCollectionIterator::withCollection(dict.get());
- require_action(iter, exit, DEBUG_ERROR("Failed to create iterator\n"));
+ iter = OSCollectionIterator::withCollection(dict);
+ if (iter == nullptr) {
+ DEBUG_ERROR("failed to create iterator\n");
+ goto exit;
+ }
DEBUG_INFO("Dumping dict...\n");
while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
count++;
DEBUG_INFO("%u: %s\n", count, key->getCStringNoCopy());
}
+
exit:
return;
}
-
-static void
-dumpData(const char *name, OSSharedPtr<OSData> propData)
-{
- if (!IS_LOG_BIT_SET(kIONVRAMDataHexDump) || !propData) {
- return;
- }
-
- uint8_t *dataBuf = (uint8_t *)propData->getBytesNoCopy();
- size_t propDataSize = propData->getLength();
-
- if (dataBuf == nullptr || propDataSize == 0) {
- return;
- }
-
- IOLog("%s:%s:%u - %s: ", __FILE_NAME__, __FUNCTION__, __LINE__, name);
- for (size_t i = 0; i < propDataSize; i++) {
- // if printable character, use that
- if ((dataBuf[i] >= 0x20 && dataBuf[i] <= 0x7e) && dataBuf[i] != '%') {
- IOLog("%c", dataBuf[i]);
- } else {
- IOLog("%%%02x", dataBuf[i]);
- }
- }
- IOLog("\n");
-}
-
-
-typedef struct {
- const char *name;
- OSSharedPtr<OSObject> value;
-} ephDMAllowListEntry;
-
-// common region variables to preserve on ephemeral boot
-static
-ephDMAllowListEntry ephDMEntries[] = {
- // Mobile Obliteration clears the following variables after it runs
- { .name = "oblit-begins" },
- { .name = "orig-oblit" },
- { .name = "oblit-failure" },
- { .name = "oblit-inprogress" },
- { .name = "obliteration" },
- // darwin-init is used for configuring internal builds
- { .name = "darwin-init" },
- { .name = "darwin-init-system" }
-};
// ************************** IODTNVRAMPlatformNotifier ****************************
// private IOService based class for passing notifications to IODTNVRAM
@@ -950,14 +788,14 @@
OSDeclareDefaultStructors(IODTNVRAMDiags)
private:
IODTNVRAM *_provider;
- IORWLock *_diagLock;
+ IORWLock *_variableLock;
OSSharedPtr<OSDictionary> _stats;
bool serializeStats(void *, OSSerialize * serializer);
public:
bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
- void logVariable(NVRAMPartitionType region, IONVRAMOperation op, const char *name, void *data = nullptr, void *offset = nullptr);
+ void logVariable(NVRAMPartitionType region, IONVRAMOperation op, const char *name, void *data);
};
OSDefineMetaClassAndStructors(IODTNVRAMDiags, IOService)
@@ -972,8 +810,8 @@
require(super::start(provider), error);
- _diagLock = IORWLockAlloc();
- require(_diagLock != nullptr, error);
+ _variableLock = IORWLockAlloc();
+ require(_variableLock != nullptr, error);
_stats = OSDictionary::withCapacity(1);
require(_stats != nullptr, error);
@@ -994,22 +832,21 @@
}
void
-IODTNVRAMDiags::logVariable(NVRAMPartitionType region, IONVRAMOperation op, const char *name, void *data, void *offset)
+IODTNVRAMDiags::logVariable(NVRAMPartitionType region, IONVRAMOperation op, const char *name, void *data)
{
// "Stats" : OSDictionary
// - "XX:varName" : OSDictionary, XX is the region value prefix to distinguish which dictionary the variable is in
- // - "Init" : OSNumber variable offset (in the proxy image passed via EDT) if variable is present at initialization (unserialize)
+ // - "Init" : OSBoolean True/present if variable present at initialization
// - "Read" : OSNumber count
// - "Write" : OSNumber count
// - "Delete" : OSNumber count
- // - "Size" : OSNumber data size, latest size from either init or write
+ // - "Size" : OSNumber size, latest size from either init or write
// - "Present" : OSBoolean True/False if variable is present or not
char *entryKey;
size_t entryKeySize;
OSSharedPtr<OSDictionary> existingEntry;
OSSharedPtr<OSNumber> currentCount;
OSSharedPtr<OSNumber> varSize;
- OSSharedPtr<OSNumber> varOffset;
const char *opCountKey = nullptr;
entryKeySize = strlen("XX:") + strlen(name) + 1;
@@ -1018,7 +855,7 @@
snprintf(entryKey, entryKeySize, "%02X:%s", region, name);
- NVRAMWRITELOCK(_diagLock);
+ NVRAMWRITELOCK();
existingEntry.reset(OSDynamicCast(OSDictionary, _stats->getObject(entryKey)), OSRetain);
if (existingEntry == nullptr) {
@@ -1046,8 +883,7 @@
break;
case kIONVRAMOperationInit:
varSize = OSNumber::withNumber((size_t)data, 64);
- varOffset = OSNumber::withNumber((size_t)offset, 64);
- existingEntry->setObject(kIODTNVRAMDiagsInitKey, varOffset);
+ existingEntry->setObject(kIODTNVRAMDiagsInitKey, varSize);
existingEntry->setObject(kIODTNVRAMDiagsSizeKey, varSize);
existingEntry->setObject(kIODTNVRAMDiagsPresentKey, kOSBooleanTrue);
break;
@@ -1070,7 +906,7 @@
_stats->setObject(entryKey, existingEntry);
unlock:
- NVRAMRWUNLOCK(_diagLock);
+ NVRAMUNLOCK();
exit:
IODeleteData(entryKey, char, entryKeySize);
@@ -1083,9 +919,9 @@
{
bool ok;
- NVRAMREADLOCK(_diagLock);
+ NVRAMREADLOCK();
ok = _stats->serialize(serializer);
- NVRAMRWUNLOCK(_diagLock);
+ NVRAMUNLOCK();
return ok;
}
@@ -1159,18 +995,20 @@
const OSSymbol *key;
OSSharedPtr<OSDictionary> dict;
OSSharedPtr<OSCollectionIterator> iter;
- OSSharedPtr<OSDictionary> localVariables;
+ OSSharedPtr<OSDictionary> localVariables = _provider->_varDict;
bool ok = false;
- IOReturn status;
-
- status = _provider->getVarDict(localVariables);
- require_noerr_action(status, exit, DEBUG_ERROR("Failed to get variable dictionary\n"));
dict = OSDictionary::withCapacity(localVariables->getCount());
- require_action(dict, exit, DEBUG_ERROR("Failed to create dict\n"));
+ if (dict == nullptr) {
+ DEBUG_ERROR("No dictionary\n");
+ goto exit;
+ }
iter = OSCollectionIterator::withCollection(localVariables.get());
- require_action(iter, exit, DEBUG_ERROR("Failed to create iterator\n"));
+ if (iter == nullptr) {
+ DEBUG_ERROR("failed to create iterator\n");
+ goto exit;
+ }
while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
if (verifyPermission(kIONVRAMOperationRead, key, _systemActive)) {
@@ -1284,7 +1122,7 @@
virtual IOReturn unserializeVariables(void) = 0;
virtual IOReturn setVariable(const uuid_t varGuid, const char *variableName, OSObject *object) = 0;
virtual bool setController(IONVRAMController *_nvramController) = 0;
- virtual IOReturn sync(void) = 0;
+ virtual bool sync(void) = 0;
virtual IOReturn flush(const uuid_t guid, IONVRAMOperation op) = 0;
virtual void reload(void) = 0;
virtual uint32_t getGeneration(void) const = 0;
@@ -1292,8 +1130,6 @@
virtual uint32_t getSystemUsed(void) const = 0;
virtual uint32_t getCommonUsed(void) const = 0;
virtual bool getSystemPartitionActive(void) const = 0;
- virtual IOReturn getVarDict(OSSharedPtr<OSDictionary> &varDictCopy) = 0;
- IOReturn handleEphDM(void);
};
IODTNVRAMFormatHandler::~IODTNVRAMFormatHandler()
@@ -1343,67 +1179,6 @@
return ok;
}
-IOReturn
-IODTNVRAMFormatHandler::handleEphDM(void)
-{
- OSSharedPtr<IORegistryEntry> entry;
- OSData* data;
- OSSharedPtr<OSObject> prop;
- uint32_t ephDM = 0;
- IOReturn ret = kIOReturnSuccess;
- OSSharedPtr<const OSSymbol> canonicalKey;
- uint32_t skip = 0;
- OSSharedPtr<OSDictionary> varDict;
-
- // For ephemeral data mode, NVRAM needs to be cleared on every boot
- // For system region supported targets, iBoot clears the system region
- // For other targets, iBoot clears all the persistent variables
- // So xnu only needs to clear the common region
- entry = IORegistryEntry::fromPath("/product", gIODTPlane);
- if (entry) {
- prop = entry->copyProperty("ephemeral-data-mode");
- if (prop) {
- data = OSDynamicCast(OSData, prop.get());
- if (data) {
- ephDM = *((uint32_t *)data->getBytesNoCopy());
- }
- }
- }
-
- require_action(ephDM != 0, exit, DEBUG_ALWAYS("ephemeral-data-mode not supported\n"));
- require_action(getSystemPartitionActive(), exit, DEBUG_ALWAYS("No system region, no need to clear\n"));
-
- if (PE_parse_boot_argn("epdm-skip-nvram", &skip, sizeof(skip))) {
- require_action(!(gInternalBuild && (skip == 1)), exit, DEBUG_ALWAYS("Internal build + epdm-skip-nvram set to true, skip nvram clearing\n"));
- }
-
- // Get the current variable dictionary
- ret = getVarDict(varDict);
- require_noerr_action(ret, exit, DEBUG_ERROR("Failed to get variable dictionary for EphDM handling\n"));
-
- // Go through the allowlist and stash the values
- for (uint32_t entry = 0; entry < ARRAY_SIZE(ephDMEntries); entry++) {
- canonicalKey = keyWithGuidAndCString(gAppleNVRAMGuid, ephDMEntries[entry].name);
- ephDMEntries[entry].value.reset(OSDynamicCast(OSData, varDict->getObject(canonicalKey.get())), OSRetain);
- }
-
- DEBUG_ALWAYS("Obliterating common region\n");
- ret = flush(gAppleNVRAMGuid, kIONVRAMOperationObliterate);
- require_noerr_action(ret, exit, DEBUG_ERROR("Flushing common region failed, ret=%#08x\n", ret));
-
- // Now write the allowlist variables back
- for (uint32_t entry = 0; entry < ARRAY_SIZE(ephDMEntries); entry++) {
- if (ephDMEntries[entry].value.get() == nullptr) {
- continue;
- }
- ret = setVariable(gAppleNVRAMGuid, ephDMEntries[entry].name, ephDMEntries[entry].value.get());
- require_noerr_action(ret, exit, DEBUG_ERROR("Setting allowlist variable %s failed, ret=%#08x\n", ephDMEntries[entry].name, ret));
- }
-
-exit:
- return ret;
-}
-
#include "IONVRAMCHRPHandler.cpp"
#include "IONVRAMV3Handler.cpp"
@@ -1416,15 +1191,21 @@
OSSharedPtr<OSDictionary> dict;
DEBUG_INFO("...\n");
+
require(super::init(old, plane), fail);
- x86Device = false;
-
-#if CONFIG_CSR && XNU_TARGET_OS_OSX
+
+#if XNU_TARGET_OS_OSX
+#if CONFIG_CSR
gInternalBuild = (csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0);
-#elif defined(DEBUG) || defined(DEVELOPMENT)
- gInternalBuild = true;
-#endif
DEBUG_INFO("gInternalBuild = %d\n", gInternalBuild);
+#endif // CONFIG_CSR
+#endif // XNU_TARGET_OS_OSX
+
+ _variableLock = IORWLockAlloc();
+ require(_variableLock != nullptr, fail);
+
+ _controllerLock = IOLockAlloc();
+ require(_controllerLock != nullptr, fail);
// Clear the IORegistryEntry property table
dict = OSDictionary::withCapacity(1);
@@ -1444,7 +1225,7 @@
{
OSSharedPtr<OSNumber> version;
- DEBUG_ALWAYS("...\n");
+ DEBUG_INFO("...\n");
require(super::start(provider), fail);
@@ -1452,7 +1233,7 @@
// If not, skip any additional initialization being done here.
// This is not an error we just need to successfully exit this function to allow
// AppleEFIRuntime to proceed and take over operation
- require_action(x86Device == false, no_common, DEBUG_INFO("x86 init\n"));
+ require_action(_controllerLock != nullptr, no_common, DEBUG_INFO("x86 init\n"));
_diags = new IODTNVRAMDiags;
if (!_diags || !_diags->init()) {
@@ -1568,8 +1349,6 @@
OSData *data = nullptr;
uint32_t size = 0;
const uint8_t *image = nullptr;
- OSSharedPtr<OSDictionary> localVariables;
- IOReturn status;
entry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
@@ -1582,7 +1361,6 @@
require(data != nullptr, skip);
size = *((uint32_t*)data->getBytesNoCopy());
- require_action(size != 0, skip, panic("NVRAM size is 0 bytes, possibly due to bad config with iBoot + xnu mismatch"));
DEBUG_ALWAYS("NVRAM size is %u bytes\n", size);
prop = entry->copyProperty(proxyDataKey);
@@ -1595,20 +1373,16 @@
skip:
if (IONVRAMV3Handler::isValidImage(image, size)) {
- _format = IONVRAMV3Handler::init(this, image, size);
+ _format = IONVRAMV3Handler::init(this, image, size, _varDict);
require_action(_format, skip, panic("IONVRAMV3Handler creation failed\n"));
} else {
- _format = IONVRAMCHRPHandler::init(this, image, size);
+ _format = IONVRAMCHRPHandler::init(this, image, size, _varDict);
require_action(_format, skip, panic("IONVRAMCHRPHandler creation failed\n"));
}
- status = _format->unserializeVariables();
- verify_noerr_action(status, DEBUG_ERROR("Failed to unserialize variables, status=%08x\n", status));
-
- status = _format->getVarDict(localVariables);
- verify_noerr_action(status, DEBUG_ERROR("Failed to get variable dictionary, status=%08x\n", status));
-
- dumpDict(localVariables);
+ _format->unserializeVariables();
+
+ dumpDict(_varDict.get());
#if defined(RELEASE)
if (entry != nullptr) {
@@ -1625,10 +1399,14 @@
{
DEBUG_INFO("setting controller\n");
- require_action(_format != nullptr, exit, DEBUG_ERROR("Handler not initialized yet\n"));
+ NVRAMWRITELOCK();
+ CONTROLLERLOCK();
+
_format->setController(controller);
-exit:
+ CONTROLLERUNLOCK();
+ NVRAMUNLOCK();
+
return;
}
@@ -1655,49 +1433,46 @@
return false;
}
-IOReturn
+void
IODTNVRAM::syncInternal(bool rateLimit)
{
- IOReturn ret = kIOReturnSuccess;
-
DEBUG_INFO("rateLimit=%d\n", rateLimit);
if (!SAFE_TO_LOCK()) {
DEBUG_INFO("cannot lock\n");
- goto exit;
- }
-
- require_action(_format != nullptr, exit, (ret = kIOReturnNotReady, DEBUG_ERROR("Handler not initialized yet\n")));
+ return;
+ }
// Rate limit requests to sync. Drivers that need this rate limiting will
// shadow the data and only write to flash when they get a sync call
if (rateLimit) {
if (safeToSync() == false) {
DEBUG_INFO("safeToSync()=false\n");
- goto exit;
+ return;
}
}
DEBUG_INFO("Calling sync()\n");
record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "sync", "triggered");
- ret = _format->sync();
-
- record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "sync", "completed with ret=%08x", ret);
+ NVRAMREADLOCK();
+ CONTROLLERLOCK();
+
+ _format->sync();
+
+ CONTROLLERUNLOCK();
+ NVRAMUNLOCK();
if (_diags) {
OSSharedPtr<OSNumber> generation = OSNumber::withNumber(_format->getGeneration(), 32);
_diags->setProperty(kCurrentGenerationCountKey, generation.get());
}
-
-exit:
- return ret;
-}
-
-IOReturn
+}
+
+void
IODTNVRAM::sync(void)
{
- return syncInternal(false);
+ syncInternal(false);
}
void
@@ -1706,38 +1481,46 @@
_format->reload();
}
-IOReturn
-IODTNVRAM::getVarDict(OSSharedPtr<OSDictionary> &varDictCopy)
-{
- return _format->getVarDict(varDictCopy);
-}
-
-OSPtr<OSDictionary>
-IODTNVRAM::dictionaryWithProperties(void) const
+bool
+IODTNVRAM::serializeProperties(OSSerialize *s) const
{
const OSSymbol *canonicalKey;
OSSharedPtr<OSDictionary> localVarDict, returnDict;
OSSharedPtr<OSCollectionIterator> iter;
+ bool ok = false;
+ unsigned int totalCapacity = 0;
uuid_t varGuid;
const char * varName;
- IOReturn status;
- require_action(_format, exit, DEBUG_ERROR("Handler not initialized yet\n"));
-
- status = _format->getVarDict(localVarDict);
- require_noerr_action(status, exit, DEBUG_ERROR("Failed to get variable dictionary\n"));
-
- returnDict = OSDictionary::withCapacity(localVarDict->getCapacity());
- require_action(returnDict, exit, DEBUG_ERROR("Failed to create return dict\n"));
+
+ NVRAMREADLOCK();
+ if (_varDict) {
+ localVarDict = OSDictionary::withDictionary(_varDict.get());
+ }
+ NVRAMUNLOCK();
+
+ if (localVarDict != nullptr) {
+ totalCapacity = localVarDict->getCapacity();
+ }
+
+ returnDict = OSDictionary::withCapacity(totalCapacity);
+
+ if (returnDict == nullptr) {
+ DEBUG_ERROR("No dictionary\n");
+ goto exit;
+ }
// Copy system entries first if present then copy unique other entries
iter = OSCollectionIterator::withCollection(localVarDict.get());
- require_action(iter, exit, DEBUG_ERROR("Failed to create iterator\n"));
+ if (iter == nullptr) {
+ DEBUG_ERROR("failed to create iterator\n");
+ goto exit;
+ }
while ((canonicalKey = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
parseVariableName(canonicalKey, &varGuid, &varName);
if ((uuid_compare(varGuid, gAppleSystemVariableGuid) == 0) &&
- verifyPermission(kIONVRAMOperationRead, varGuid, varName, _format->getSystemPartitionActive(), false)) {
+ verifyPermission(kIONVRAMOperationRead, varGuid, varName, _format->getSystemPartitionActive())) {
OSSharedPtr<const OSSymbol> returnKey = OSSymbol::withCString(varName);
returnDict->setObject(returnKey.get(), localVarDict->getObject(canonicalKey));
}
@@ -1746,7 +1529,10 @@
iter.reset();
iter = OSCollectionIterator::withCollection(localVarDict.get());
- require_action(iter, exit, DEBUG_ERROR("Failed to create iterator\n"));
+ if (iter == nullptr) {
+ DEBUG_ERROR("failed to create iterator\n");
+ goto exit;
+ }
while ((canonicalKey = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
parseVariableName(canonicalKey, &varGuid, &varName);
@@ -1757,28 +1543,18 @@
continue;
}
- if (verifyPermission(kIONVRAMOperationRead, varGuid, varName, _format->getSystemPartitionActive(), false)) {
+ if (verifyPermission(kIONVRAMOperationRead, varGuid, varName, _format->getSystemPartitionActive())) {
OSSharedPtr<const OSSymbol> returnKey = OSSymbol::withCString(varName);
returnDict->setObject(returnKey.get(), localVarDict->getObject(canonicalKey));
}
}
}
+
+ ok = returnDict->serialize(s);
+
exit:
- return returnDict;
-}
-
-bool
-IODTNVRAM::serializeProperties(OSSerialize *s) const
-{
- bool ok = false;
- OSSharedPtr<OSDictionary> dict;
-
- dict = dictionaryWithProperties();
- if (dict) {
- ok = dict->serialize(s);
- }
-
DEBUG_INFO("ok=%d\n", ok);
+
return ok;
}
@@ -1786,8 +1562,6 @@
IODTNVRAM::flushGUID(const uuid_t guid, IONVRAMOperation op)
{
IOReturn ret = kIOReturnSuccess;
-
- require_action(_format != nullptr, exit, (ret = kIOReturnNotReady, DEBUG_ERROR("Handler not initialized yet\n")));
if (_format->getSystemPartitionActive() && (uuid_compare(guid, gAppleSystemVariableGuid) == 0)) {
ret = _format->flush(guid, op);
@@ -1799,7 +1573,6 @@
DEBUG_INFO("common variables flushed, ret=%08x\n", ret);
}
-exit:
return ret;
}
@@ -1808,6 +1581,8 @@
{
IOReturn ret = kIOReturnSuccess;
bool special = false;
+
+ NVRAMLOCKASSERTEXCLUSIVE();
// ResetNVRam flushes both regions in one call
// Obliterate can flush either separately
@@ -1839,27 +1614,27 @@
OSSharedPtr<const OSSymbol> canonicalKey;
OSSharedPtr<OSObject> theObject;
uuid_t newGuid;
- OSSharedPtr<OSDictionary> localVarDict;
- IOReturn status;
-
- require_action(_format, exit, DEBUG_ERROR("Handler not initialized yet\n"));
-
- status = _format->getVarDict(localVarDict);
- require_noerr_action(status, exit, DEBUG_ERROR("Failed to get variable dictionary\n"));
-
- if (!verifyPermission(kIONVRAMOperationRead, guid, name, _format->getSystemPartitionActive(), true)) {
+
+ if (_varDict == nullptr) {
+ DEBUG_INFO("No dictionary\n");
+ goto exit;
+ }
+
+ if (!verifyPermission(kIONVRAMOperationRead, guid, name, _format->getSystemPartitionActive())) {
DEBUG_INFO("Not privileged\n");
goto exit;
}
- translateGUID(guid, name, newGuid, _format->getSystemPartitionActive(), true);
+ translateGUID(guid, name, newGuid, _format->getSystemPartitionActive());
canonicalKey = keyWithGuidAndCString(newGuid, name);
- theObject.reset(localVarDict->getObject(canonicalKey.get()), OSRetain);
+ NVRAMREADLOCK();
+ theObject.reset(_varDict->getObject(canonicalKey.get()), OSRetain);
+ NVRAMUNLOCK();
if (_diags) {
- _diags->logVariable(getPartitionTypeForGUID(newGuid), kIONVRAMOperationRead, name);
+ _diags->logVariable(getPartitionTypeForGUID(newGuid), kIONVRAMOperationRead, name, NULL);
}
if (theObject != nullptr) {
@@ -1920,29 +1695,6 @@
OSSharedPtr<OSObject> theObject = copyProperty(aKey);
return theObject.get();
-}
-
-IOReturn
-IODTNVRAM::clearTestVars(const uuid_t guid)
-{
- const VariablePermissionEntry *entry;
- IOReturn ret = kIOReturnSuccess;
- uuid_t newGuid;
-
- entry = gVariablePermissions;
- require_action(gInternalBuild, exit, DEBUG_INFO("Internal build only\n"));
- require_action(_format != nullptr, exit, (ret = kIOReturnNotReady, DEBUG_ERROR("Handler not initialized yet\n")));
-
- while ((entry != nullptr) && (entry->name != nullptr)) {
- if (entry->p.Bits.TestingOnly) {
- translateGUID(guid, entry->name, newGuid, _format->getSystemPartitionActive(), true);
- ret = _format->setVariable(newGuid, entry->name, nullptr);
- }
- entry++;
- }
-
-exit:
- return ret;
}
IOReturn
@@ -1953,24 +1705,16 @@
OSString *tmpString = nullptr;
OSSharedPtr<OSObject> propObject;
OSSharedPtr<OSObject> sharedObject(anObject, OSRetain);
- bool deletePropertyKey, syncNowPropertyKey, forceSyncNowPropertyKey, deletePropertyKeyWRet;
+ bool deletePropertyKey, syncNowPropertyKey, forceSyncNowPropertyKey;
bool ok;
size_t propDataSize = 0;
uuid_t newGuid;
- require_action(_format != nullptr, exit, (ret = kIOReturnNotReady, DEBUG_ERROR("Handler not initialized yet\n")));
-
- if (strncmp(name, kNVRAMClearTestVarKey, sizeof(kNVRAMClearTestVarKey)) == 0) {
- ret = clearTestVars(guid);
- goto exit;
- }
-
deletePropertyKey = strncmp(name, kIONVRAMDeletePropertyKey, sizeof(kIONVRAMDeletePropertyKey)) == 0;
- deletePropertyKeyWRet = strncmp(name, kIONVRAMDeletePropertyKeyWRet, sizeof(kIONVRAMDeletePropertyKeyWRet)) == 0;
syncNowPropertyKey = strncmp(name, kIONVRAMSyncNowPropertyKey, sizeof(kIONVRAMSyncNowPropertyKey)) == 0;
forceSyncNowPropertyKey = strncmp(name, kIONVRAMForceSyncNowPropertyKey, sizeof(kIONVRAMForceSyncNowPropertyKey)) == 0;
- if (deletePropertyKey || deletePropertyKeyWRet) {
+ if (deletePropertyKey) {
tmpString = OSDynamicCast(OSString, anObject);
if (tmpString != nullptr) {
const char *variableName;
@@ -1994,12 +1738,10 @@
DEBUG_INFO("Removing with value provided GUID\n");
removeRet = removePropertyWithGUIDAndName(valueVarGuid, variableName);
}
- if (deletePropertyKeyWRet) {
- ret = removeRet;
- }
- DEBUG_INFO("%s found, removeRet=%#08x\n", deletePropertyKeyWRet ? "deletePropertyKeyWRet" : "deletePropertyKey", removeRet);
+
+ DEBUG_INFO("kIONVRAMDeletePropertyKey found, removeRet=%#08x\n", removeRet);
} else {
- DEBUG_INFO("%s value needs to be an OSString\n", deletePropertyKeyWRet ? "deletePropertyKeyWRet" : "deletePropertyKey");
+ DEBUG_INFO("kIONVRAMDeletePropertyKey value needs to be an OSString\n");
ret = kIOReturnError;
}
goto exit;
@@ -2008,7 +1750,7 @@
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.
- ret = syncInternal(syncNowPropertyKey);
+ syncInternal(syncNowPropertyKey);
} else {
DEBUG_INFO("%s value needs to be an OSString\n", name);
ret = kIOReturnError;
@@ -2016,7 +1758,7 @@
goto exit;
}
- if (!verifyPermission(kIONVRAMOperationWrite, guid, name, _format->getSystemPartitionActive(), true)) {
+ if (!verifyPermission(kIONVRAMOperationWrite, guid, name, _format->getSystemPartitionActive())) {
DEBUG_INFO("Not privileged\n");
ret = kIOReturnNotPrivileged;
goto exit;
@@ -2027,21 +1769,21 @@
case kOFVariableTypeBoolean:
propObject = OSDynamicPtrCast<OSBoolean>(sharedObject);
if (propObject) {
- record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as bool to %d", name, ((OSBoolean *)propObject.get())->getValue());
+ record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s to %d", name, ((OSBoolean *)propObject.get())->getValue());
}
break;
case kOFVariableTypeNumber:
propObject = OSDynamicPtrCast<OSNumber>(sharedObject);
if (propObject) {
- record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as number to %#llx", name, ((OSNumber *)propObject.get())->unsigned64BitValue());
+ record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s to %#llx", name, ((OSNumber *)propObject.get())->unsigned64BitValue());
}
break;
case kOFVariableTypeString:
propObject = OSDynamicPtrCast<OSString>(sharedObject);
if (propObject != nullptr) {
- record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as string to %s", name, ((OSString *)propObject.get())->getCStringNoCopy());
+ record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s to %s", name, ((OSString *)propObject.get())->getCStringNoCopy());
propDataSize = (OSDynamicPtrCast<OSString>(propObject))->getLength();
@@ -2064,10 +1806,8 @@
}
if (propObject != nullptr) {
- OSSharedPtr<OSData> propData = OSDynamicPtrCast<OSData>(propObject);
- propDataSize = propData->getLength();
- record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as data with size %zu", name, propDataSize);
- dumpData(name, propData);
+ propDataSize = (OSDynamicPtrCast<OSData>(propObject))->getLength();
+ record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s with data size %#x", name, ((OSData *)propObject.get())->getLength());
}
#if defined(XNU_TARGET_OS_OSX)
@@ -2081,7 +1821,7 @@
}
if (propObject == nullptr) {
- DEBUG_ERROR("No property object\n");
+ DEBUG_INFO("No property object\n");
ret = kIOReturnBadArgument;
goto exit;
}
@@ -2092,7 +1832,9 @@
goto exit;
}
+ NVRAMWRITELOCK();
ok = handleSpecialVariables(name, guid, propObject.get(), &ret);
+ NVRAMUNLOCK();
if (ok) {
goto exit;
@@ -2101,8 +1843,13 @@
if (remove == false) {
DEBUG_INFO("Adding object\n");
- translateGUID(guid, name, newGuid, _format->getSystemPartitionActive(), true);
+ translateGUID(guid, name, newGuid, _format->getSystemPartitionActive());
+
+ NVRAMWRITELOCK();
+
ret = _format->setVariable(newGuid, name, propObject.get());
+
+ NVRAMUNLOCK();
} else {
DEBUG_INFO("Removing object\n");
ret = removePropertyWithGUIDAndName(guid, name);
@@ -2156,21 +1903,31 @@
uuid_t newGuid;
DEBUG_INFO("name=%s\n", name);
- require_action(_format != nullptr, exit, (ret = kIOReturnNotReady, DEBUG_ERROR("Handler not initialized yet\n")));
-
- if (!verifyPermission(kIONVRAMOperationDelete, guid, name, _format->getSystemPartitionActive(), true)) {
+
+ if (_varDict == nullptr) {
+ DEBUG_INFO("No dictionary\n");
+ ret = kIOReturnNotFound;
+ goto exit;
+ }
+
+ if (!verifyPermission(kIONVRAMOperationDelete, guid, name, _format->getSystemPartitionActive())) {
DEBUG_INFO("Not privileged\n");
ret = kIOReturnNotPrivileged;
goto exit;
}
- translateGUID(guid, name, newGuid, _format->getSystemPartitionActive(), true);
+ translateGUID(guid, name, newGuid, _format->getSystemPartitionActive());
+
+ NVRAMWRITELOCK();
+
ret = _format->setVariable(newGuid, name, nullptr);
if (ret != kIOReturnSuccess) {
DEBUG_INFO("%s not found\n", name);
ret = kIOReturnNotFound;
}
+
+ NVRAMUNLOCK();
record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "delete", "%s", name);