xref: /xnu-11215/iokit/Kernel/IONVRAM.cpp (revision 8d741a5d)
1c1dac77fSApple OSS Distributions /*
2e13b1fa5SApple OSS Distributions  * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
3e7776783SApple OSS Distributions  * Copyright (c) 2007-2021 Apple Inc. All rights reserved.
4c1dac77fSApple OSS Distributions  *
5e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6c1dac77fSApple OSS Distributions  *
7e13b1fa5SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
8e13b1fa5SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
9e13b1fa5SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
10e13b1fa5SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
11e13b1fa5SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
12e13b1fa5SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
13e13b1fa5SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
14e13b1fa5SApple OSS Distributions  * terms of an Apple operating system software license agreement.
15c1dac77fSApple OSS Distributions  *
16e13b1fa5SApple OSS Distributions  * Please obtain a copy of the License at
17e13b1fa5SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
18e13b1fa5SApple OSS Distributions  *
19e13b1fa5SApple OSS Distributions  * The Original Code and all software distributed under the License are
20e13b1fa5SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21c1dac77fSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22c1dac77fSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23e13b1fa5SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24e13b1fa5SApple OSS Distributions  * Please see the License for the specific language governing rights and
25e13b1fa5SApple OSS Distributions  * limitations under the License.
26c1dac77fSApple OSS Distributions  *
27e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28c1dac77fSApple OSS Distributions  */
29c1dac77fSApple OSS Distributions 
30bb611c8fSApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR
31bb611c8fSApple OSS Distributions 
32bb611c8fSApple OSS Distributions #include <AssertMacros.h>
33c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h>
34c1dac77fSApple OSS Distributions #include <IOKit/IONVRAM.h>
35c1dac77fSApple OSS Distributions #include <IOKit/IOPlatformExpert.h>
36c1dac77fSApple OSS Distributions #include <IOKit/IOUserClient.h>
37c1dac77fSApple OSS Distributions #include <IOKit/IOKitKeys.h>
380f3703acSApple OSS Distributions #include <IOKit/IOKitKeysPrivate.h>
39bb611c8fSApple OSS Distributions #include <IOKit/IOBSD.h>
403ca3bd55SApple OSS Distributions #include <kern/debug.h>
415c2921b0SApple OSS Distributions #include <os/system_event_log.h>
42*8d741a5dSApple OSS Distributions #include <pexpert/boot.h>
43e6231be0SApple OSS Distributions #include <sys/csr.h>
44c1dac77fSApple OSS Distributions 
45c1dac77fSApple OSS Distributions #define super IOService
46c1dac77fSApple OSS Distributions 
47e6231be0SApple OSS Distributions OSDefineMetaClassAndStructors(IODTNVRAM, IOService);
48e6231be0SApple OSS Distributions 
49e7776783SApple OSS Distributions class IONVRAMCHRPHandler;
50e7776783SApple OSS Distributions class IONVRAMV3Handler;
51e7776783SApple OSS Distributions 
52bb611c8fSApple OSS Distributions #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
53bb611c8fSApple OSS Distributions 
54e6231be0SApple OSS Distributions #define MAX_VAR_NAME_SIZE     63
55bb611c8fSApple OSS Distributions 
565c2921b0SApple OSS Distributions #define kNVRAMBankSizeKey    "nvram-bank-size"
575c2921b0SApple OSS Distributions #define kNVRAMBankCountKey   "nvram-bank-count"
585c2921b0SApple OSS Distributions #define kNVRAMCurrentBankKey "nvram-current-bank"
595c2921b0SApple OSS Distributions 
60e6231be0SApple OSS Distributions #define kCurrentGenerationCountKey "Generation"
61e6231be0SApple OSS Distributions #define kCurrentNVRAMVersionKey    "Version"
62bb611c8fSApple OSS Distributions 
63e7776783SApple OSS Distributions #define kNVRAMCommonUsedKey    "CommonUsed"
64e7776783SApple OSS Distributions #define kNVRAMSystemUsedKey    "SystemUsed"
65bb611c8fSApple OSS Distributions 
6614e3d835SApple OSS Distributions #define kIONVRAMPrivilege       kIOClientPrivilegeAdministrator
6714e3d835SApple OSS Distributions 
68e6231be0SApple OSS Distributions #define MIN_SYNC_NOW_INTERVAL 15*60 /* Minimum 15 Minutes interval mandated */
69c1dac77fSApple OSS Distributions 
70bb611c8fSApple OSS Distributions #if defined(DEBUG) || defined(DEVELOPMENT)
715c2921b0SApple OSS Distributions #define DEBUG_IFERROR(err, fmt, args...)                                     \
725c2921b0SApple OSS Distributions ({                                                                           \
735c2921b0SApple OSS Distributions 	if ((err != kIOReturnSuccess) || gNVRAMLogging)                          \
745c2921b0SApple OSS Distributions 	IOLog("%s:%s:%u - " fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##args); \
755c2921b0SApple OSS Distributions })
765c2921b0SApple OSS Distributions 
77bb611c8fSApple OSS Distributions #define DEBUG_INFO(fmt, args...)                                             \
78bb611c8fSApple OSS Distributions ({                                                                           \
79bb611c8fSApple OSS Distributions 	if (gNVRAMLogging)                                                       \
80e7776783SApple OSS Distributions 	IOLog("%s:%s:%u - " fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##args); \
81bb611c8fSApple OSS Distributions })
82bb611c8fSApple OSS Distributions 
83bb611c8fSApple OSS Distributions #define DEBUG_ALWAYS(fmt, args...)                                           \
84bb611c8fSApple OSS Distributions ({                                                                           \
85e7776783SApple OSS Distributions 	IOLog("%s:%s:%u - " fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##args); \
86bb611c8fSApple OSS Distributions })
87bb611c8fSApple OSS Distributions #else
885c2921b0SApple OSS Distributions #define DEBUG_IFERROR(err, fmt, args...) (void)NULL
89e6231be0SApple OSS Distributions #define DEBUG_INFO(fmt, args...) (void)NULL
90e6231be0SApple OSS Distributions #define DEBUG_ALWAYS(fmt, args...) (void)NULL
91bb611c8fSApple OSS Distributions #endif
92bb611c8fSApple OSS Distributions 
93bb611c8fSApple OSS Distributions #define DEBUG_ERROR DEBUG_ALWAYS
94bb611c8fSApple OSS Distributions 
95e6231be0SApple OSS Distributions #define SAFE_TO_LOCK() (preemption_enabled() && !panic_active())
96e6231be0SApple OSS Distributions 
97e6231be0SApple OSS Distributions #define CONTROLLERLOCK()                     \
98bb611c8fSApple OSS Distributions ({                                           \
99e6231be0SApple OSS Distributions 	if (SAFE_TO_LOCK())                  \
100e6231be0SApple OSS Distributions 	        IOLockLock(_controllerLock); \
101e6231be0SApple OSS Distributions })
102e6231be0SApple OSS Distributions 
103e6231be0SApple OSS Distributions #define CONTROLLERUNLOCK()                     \
104e6231be0SApple OSS Distributions ({                                             \
105e6231be0SApple OSS Distributions 	if (SAFE_TO_LOCK())                    \
106e6231be0SApple OSS Distributions 	        IOLockUnlock(_controllerLock); \
107e6231be0SApple OSS Distributions })
108e6231be0SApple OSS Distributions 
109e6231be0SApple OSS Distributions #define NVRAMREADLOCK()                       \
110e6231be0SApple OSS Distributions ({                                            \
111e6231be0SApple OSS Distributions 	if (SAFE_TO_LOCK())                   \
112e6231be0SApple OSS Distributions 	        IORWLockRead(_variableLock);  \
113e6231be0SApple OSS Distributions })
114e6231be0SApple OSS Distributions 
115e6231be0SApple OSS Distributions #define NVRAMWRITELOCK()                      \
116e6231be0SApple OSS Distributions ({                                            \
117e6231be0SApple OSS Distributions 	if (SAFE_TO_LOCK())                   \
118e6231be0SApple OSS Distributions 	        IORWLockWrite(_variableLock); \
119bb611c8fSApple OSS Distributions })
120bb611c8fSApple OSS Distributions 
121bb611c8fSApple OSS Distributions #define NVRAMUNLOCK()                          \
122bb611c8fSApple OSS Distributions ({                                             \
123e6231be0SApple OSS Distributions 	if (SAFE_TO_LOCK())                    \
124e6231be0SApple OSS Distributions 	        IORWLockUnlock(_variableLock); \
125bb611c8fSApple OSS Distributions })
126bb611c8fSApple OSS Distributions 
127e6231be0SApple OSS Distributions #define NVRAMLOCKASSERTHELD()                                       \
128bb611c8fSApple OSS Distributions ({                                                                  \
129e6231be0SApple OSS Distributions 	if (SAFE_TO_LOCK())                                         \
130e6231be0SApple OSS Distributions 	        IORWLockAssert(_variableLock, kIORWLockAssertHeld); \
131bb611c8fSApple OSS Distributions })
132bb611c8fSApple OSS Distributions 
133e6231be0SApple OSS Distributions #define NVRAMLOCKASSERTEXCLUSIVE()                                   \
134e6231be0SApple OSS Distributions ({                                                                   \
135e6231be0SApple OSS Distributions 	if (SAFE_TO_LOCK())                                          \
136e6231be0SApple OSS Distributions 	        IORWLockAssert(_variableLock, kIORWLockAssertWrite); \
137e6231be0SApple OSS Distributions })
138e6231be0SApple OSS Distributions 
1391031c584SApple OSS Distributions // MOD = Write, Delete
1401031c584SApple OSS Distributions // RST = Reset, Obliterate
1411031c584SApple OSS Distributions // RD  = Read
1421031c584SApple OSS Distributions // DEL = Delete
1431031c584SApple OSS Distributions #define ENT_MOD_RST     ((1 << kIONVRAMOperationWrite)      | (1 << kIONVRAMOperationDelete)  | (1 << kIONVRAMOperationObliterate) | (1 << kIONVRAMOperationReset))
1441031c584SApple OSS Distributions #define ENT_MOD_RD      ((1 << kIONVRAMOperationRead)       | (1 << kIONVRAMOperationWrite)   | (1 << kIONVRAMOperationDelete))
1451031c584SApple OSS Distributions #define ENT_MOD         ((1 << kIONVRAMOperationWrite)      | (1 << kIONVRAMOperationDelete))
1461031c584SApple OSS Distributions #define ENT_RST         ((1 << kIONVRAMOperationObliterate) | (1 << kIONVRAMOperationReset))
1471031c584SApple OSS Distributions #define ENT_RD          ((1 << kIONVRAMOperationRead))
1481031c584SApple OSS Distributions #define ENT_DEL         ((1 << kIONVRAMOperationDelete))
149aca3beaaSApple OSS Distributions 
150e6231be0SApple OSS Distributions enum NVRAMVersion {
151e6231be0SApple OSS Distributions 	kNVRAMVersionUnknown,
152e6231be0SApple OSS Distributions 	kNVRAMVersion1,       // Legacy, banks, 0x800 common partition size
153e6231be0SApple OSS Distributions 	kNVRAMVersion2,       // V1 but with (0x2000 - sizeof(struct apple_nvram_header) - sizeof(struct chrp_nvram_header)) common region
154e7776783SApple OSS Distributions 	kNVRAMVersion3,       // New EFI based format
155e6231be0SApple OSS Distributions 	kNVRAMVersionMax
156e6231be0SApple OSS Distributions };
157e6231be0SApple OSS Distributions 
158bb611c8fSApple OSS Distributions // Guid for Apple System Boot variables
159bb611c8fSApple OSS Distributions // 40A0DDD2-77F8-4392-B4A3-1E7304206516
160bb611c8fSApple OSS Distributions UUID_DEFINE(gAppleSystemVariableGuid, 0x40, 0xA0, 0xDD, 0xD2, 0x77, 0xF8, 0x43, 0x92, 0xB4, 0xA3, 0x1E, 0x73, 0x04, 0x20, 0x65, 0x16);
161bb611c8fSApple OSS Distributions 
162bb611c8fSApple OSS Distributions // Apple NVRAM Variable namespace (APPLE_VENDOR_OS_VARIABLE_GUID)
163bb611c8fSApple OSS Distributions // 7C436110-AB2A-4BBB-A880-FE41995C9F82
164bb611c8fSApple OSS Distributions UUID_DEFINE(gAppleNVRAMGuid, 0x7C, 0x43, 0x61, 0x10, 0xAB, 0x2A, 0x4B, 0xBB, 0xA8, 0x80, 0xFE, 0x41, 0x99, 0x5C, 0x9F, 0x82);
165bb611c8fSApple OSS Distributions 
16694d3b452SApple OSS Distributions // Wifi NVRAM namespace
16794d3b452SApple OSS Distributions // 36C28AB5-6566-4C50-9EBD-CBB920F83843
16894d3b452SApple OSS Distributions UUID_DEFINE(gAppleWifiGuid, 0x36, 0xC2, 0x8A, 0xB5, 0x65, 0x66, 0x4C, 0x50, 0x9E, 0xBD, 0xCB, 0xB9, 0x20, 0xF8, 0x38, 0x43);
16994d3b452SApple OSS Distributions 
1701031c584SApple OSS Distributions // Prefix for kernel-only variables
1711031c584SApple OSS Distributions #define KERNEL_ONLY_VAR_NAME_PREFIX "krn."
1721031c584SApple OSS Distributions 
173e6231be0SApple OSS Distributions static TUNABLE(bool, gNVRAMLogging, "nvram-log", false);
174e6231be0SApple OSS Distributions static bool gInternalBuild = false;
175bb611c8fSApple OSS Distributions 
17694d3b452SApple OSS Distributions // IONVRAMSystemVariableListInternal:
17794d3b452SApple OSS Distributions // Used for internal builds only
17894d3b452SApple OSS Distributions // "force-lock-bits" used by fwam over ssh nvram to device so they are unable to use entitlements
179*8d741a5dSApple OSS Distributions // "stress-rack" used in SEG stress-rack restore prdocs
18094d3b452SApple OSS Distributions #define IONVRAMSystemVariableListInternal IONVRAMSystemVariableList, \
181*8d741a5dSApple OSS Distributions 	                                      "force-lock-bits", \
182*8d741a5dSApple OSS Distributions 	                                      "stress-rack"
18394d3b452SApple OSS Distributions 
184bb611c8fSApple OSS Distributions // allowlist variables from macboot that need to be set/get from system region if present
1855c2921b0SApple OSS Distributions static const char * const gNVRAMSystemList[] = { IONVRAMSystemVariableList, nullptr };
18694d3b452SApple OSS Distributions static const char * const gNVRAMSystemListInternal[] = { IONVRAMSystemVariableListInternal, nullptr };
187bb611c8fSApple OSS Distributions 
188bb611c8fSApple OSS Distributions typedef struct {
189bb611c8fSApple OSS Distributions 	const char *name;
190bb611c8fSApple OSS Distributions 	IONVRAMVariableType type;
191bb611c8fSApple OSS Distributions } VariableTypeEntry;
192bb611c8fSApple OSS Distributions 
193bb611c8fSApple OSS Distributions static const
194bb611c8fSApple OSS Distributions VariableTypeEntry gVariableTypes[] = {
195bb611c8fSApple OSS Distributions 	{"auto-boot?", kOFVariableTypeBoolean},
196bb611c8fSApple OSS Distributions 	{"boot-args", kOFVariableTypeString},
197bb611c8fSApple OSS Distributions 	{"boot-command", kOFVariableTypeString},
198bb611c8fSApple OSS Distributions 	{"boot-device", kOFVariableTypeString},
199bb611c8fSApple OSS Distributions 	{"boot-file", kOFVariableTypeString},
200bb611c8fSApple OSS Distributions 	{"boot-screen", kOFVariableTypeString},
201bb611c8fSApple OSS Distributions 	{"boot-script", kOFVariableTypeString},
202bb611c8fSApple OSS Distributions 	{"console-screen", kOFVariableTypeString},
203bb611c8fSApple OSS Distributions 	{"default-client-ip", kOFVariableTypeString},
204bb611c8fSApple OSS Distributions 	{"default-gateway-ip", kOFVariableTypeString},
205bb611c8fSApple OSS Distributions 	{"default-mac-address?", kOFVariableTypeBoolean},
206bb611c8fSApple OSS Distributions 	{"default-router-ip", kOFVariableTypeString},
207bb611c8fSApple OSS Distributions 	{"default-server-ip", kOFVariableTypeString},
208bb611c8fSApple OSS Distributions 	{"default-subnet-mask", kOFVariableTypeString},
209bb611c8fSApple OSS Distributions 	{"diag-device", kOFVariableTypeString},
210bb611c8fSApple OSS Distributions 	{"diag-file", kOFVariableTypeString},
211bb611c8fSApple OSS Distributions 	{"diag-switch?", kOFVariableTypeBoolean},
212bb611c8fSApple OSS Distributions 	{"fcode-debug?", kOFVariableTypeBoolean},
213bb611c8fSApple OSS Distributions 	{"input-device", kOFVariableTypeString},
214bb611c8fSApple OSS Distributions 	{"input-device-1", kOFVariableTypeString},
215bb611c8fSApple OSS Distributions 	{"little-endian?", kOFVariableTypeBoolean},
2161031c584SApple OSS Distributions 	{"ldm", kOFVariableTypeBoolean},
217bb611c8fSApple OSS Distributions 	{"load-base", kOFVariableTypeNumber},
218bb611c8fSApple OSS Distributions 	{"mouse-device", kOFVariableTypeString},
219bb611c8fSApple OSS Distributions 	{"nvramrc", kOFVariableTypeString},
220bb611c8fSApple OSS Distributions 	{"oem-banner", kOFVariableTypeString},
221bb611c8fSApple OSS Distributions 	{"oem-banner?", kOFVariableTypeBoolean},
222bb611c8fSApple OSS Distributions 	{"oem-logo", kOFVariableTypeString},
223bb611c8fSApple OSS Distributions 	{"oem-logo?", kOFVariableTypeBoolean},
224bb611c8fSApple OSS Distributions 	{"output-device", kOFVariableTypeString},
225bb611c8fSApple OSS Distributions 	{"output-device-1", kOFVariableTypeString},
226bb611c8fSApple OSS Distributions 	{"pci-probe-list", kOFVariableTypeNumber},
227bb611c8fSApple OSS Distributions 	{"pci-probe-mask", kOFVariableTypeNumber},
228bb611c8fSApple OSS Distributions 	{"real-base", kOFVariableTypeNumber},
229bb611c8fSApple OSS Distributions 	{"real-mode?", kOFVariableTypeBoolean},
230bb611c8fSApple OSS Distributions 	{"real-size", kOFVariableTypeNumber},
231bb611c8fSApple OSS Distributions 	{"screen-#columns", kOFVariableTypeNumber},
232bb611c8fSApple OSS Distributions 	{"screen-#rows", kOFVariableTypeNumber},
233bb611c8fSApple OSS Distributions 	{"security-mode", kOFVariableTypeString},
234bb611c8fSApple OSS Distributions 	{"selftest-#megs", kOFVariableTypeNumber},
235bb611c8fSApple OSS Distributions 	{"use-generic?", kOFVariableTypeBoolean},
236bb611c8fSApple OSS Distributions 	{"use-nvramrc?", kOFVariableTypeBoolean},
237bb611c8fSApple OSS Distributions 	{"virt-base", kOFVariableTypeNumber},
238bb611c8fSApple OSS Distributions 	{"virt-size", kOFVariableTypeNumber},
2391031c584SApple OSS Distributions 	// Variables used for testing
2401031c584SApple OSS Distributions 	{"test-bool", kOFVariableTypeBoolean},
2411031c584SApple OSS Distributions 	{"test-num", kOFVariableTypeNumber},
2421031c584SApple OSS Distributions 	{"test-str", kOFVariableTypeString},
2431031c584SApple OSS Distributions 	{"test-data", kOFVariableTypeData},
244bb611c8fSApple OSS Distributions #if !defined(__x86_64__)
245bb611c8fSApple OSS Distributions 	{"acc-cm-override-charger-count", kOFVariableTypeNumber},
246bb611c8fSApple OSS Distributions 	{"acc-cm-override-count", kOFVariableTypeNumber},
247bb611c8fSApple OSS Distributions 	{"acc-mb-ld-lifetime", kOFVariableTypeNumber},
248bb611c8fSApple OSS Distributions 	{"com.apple.System.boot-nonce", kOFVariableTypeString},
249bb611c8fSApple OSS Distributions 	{"darkboot", kOFVariableTypeBoolean},
250bb611c8fSApple OSS Distributions 	{"enter-tdm-mode", kOFVariableTypeBoolean},
251bb611c8fSApple OSS Distributions #endif /* !defined(__x86_64__) */
252bb611c8fSApple OSS Distributions 	{nullptr, kOFVariableTypeData} // Default type to return
253bb611c8fSApple OSS Distributions };
254bb611c8fSApple OSS Distributions 
255bb611c8fSApple OSS Distributions union VariablePermission {
256bb611c8fSApple OSS Distributions 	struct {
257bb611c8fSApple OSS Distributions 		uint64_t UserWrite            :1;
258bb611c8fSApple OSS Distributions 		uint64_t RootRequired         :1;
259bb611c8fSApple OSS Distributions 		uint64_t KernelOnly           :1;
260bb611c8fSApple OSS Distributions 		uint64_t ResetNVRAMOnlyDelete :1;
261bb611c8fSApple OSS Distributions 		uint64_t NeverAllowedToDelete :1;
262e6231be0SApple OSS Distributions 		uint64_t SystemReadHidden     :1;
263bb611c8fSApple OSS Distributions 		uint64_t FullAccess           :1;
26494d3b452SApple OSS Distributions 		uint64_t InternalOnly         :1;
265e6231be0SApple OSS Distributions 		uint64_t Reserved:57;
266bb611c8fSApple OSS Distributions 	} Bits;
267bb611c8fSApple OSS Distributions 	uint64_t Uint64;
268bb611c8fSApple OSS Distributions };
269bb611c8fSApple OSS Distributions 
270bb611c8fSApple OSS Distributions typedef struct {
271bb611c8fSApple OSS Distributions 	const char *name;
272bb611c8fSApple OSS Distributions 	VariablePermission p;
273bb611c8fSApple OSS Distributions } VariablePermissionEntry;
274bb611c8fSApple OSS Distributions 
275bb611c8fSApple OSS Distributions static const
276bb611c8fSApple OSS Distributions VariablePermissionEntry gVariablePermissions[] = {
277bb611c8fSApple OSS Distributions 	{"aapl,pci", .p.Bits.RootRequired = 1},
278bb611c8fSApple OSS Distributions 	{"battery-health", .p.Bits.RootRequired = 1,
279bb611c8fSApple OSS Distributions 	 .p.Bits.NeverAllowedToDelete = 1},
280bb611c8fSApple OSS Distributions 	{"boot-image", .p.Bits.UserWrite = 1},
281bb611c8fSApple OSS Distributions 	{"com.apple.System.fp-state", .p.Bits.KernelOnly = 1},
282e6231be0SApple OSS Distributions 	{"fm-account-masked", .p.Bits.RootRequired = 1,
283e6231be0SApple OSS Distributions 	 .p.Bits.NeverAllowedToDelete = 1},
284e6231be0SApple OSS Distributions 	{"fm-activation-locked", .p.Bits.RootRequired = 1,
285e6231be0SApple OSS Distributions 	 .p.Bits.NeverAllowedToDelete = 1},
286e6231be0SApple OSS Distributions 	{"fm-spkeys", .p.Bits.RootRequired = 1,
287e6231be0SApple OSS Distributions 	 .p.Bits.NeverAllowedToDelete = 1},
288e6231be0SApple OSS Distributions 	{"fm-spstatus", .p.Bits.RootRequired = 1,
289e6231be0SApple OSS Distributions 	 .p.Bits.NeverAllowedToDelete = 1},
290e6231be0SApple OSS Distributions 	{"policy-nonce-digests", .p.Bits.ResetNVRAMOnlyDelete = 1}, // Deleting this via user triggered obliterate leave J273a unable to boot
291e6231be0SApple OSS Distributions 	{"recoveryos-passcode-blob", .p.Bits.SystemReadHidden = 1},
292bb611c8fSApple OSS Distributions 	{"security-password", .p.Bits.RootRequired = 1},
293e6231be0SApple OSS Distributions 	{"system-passcode-lock-blob", .p.Bits.SystemReadHidden = 1},
294bb611c8fSApple OSS Distributions 
295bb611c8fSApple OSS Distributions #if !defined(__x86_64__)
296bb611c8fSApple OSS Distributions 	{"acc-cm-override-charger-count", .p.Bits.KernelOnly = 1},
297bb611c8fSApple OSS Distributions 	{"acc-cm-override-count", .p.Bits.KernelOnly = 1},
298bb611c8fSApple OSS Distributions 	{"acc-mb-ld-lifetime", .p.Bits.KernelOnly = 1},
299bb611c8fSApple OSS Distributions 	{"backlight-level", .p.Bits.UserWrite = 1},
300e6231be0SApple OSS Distributions 	{"backlight-nits", .p.Bits.UserWrite = 1},
3011031c584SApple OSS Distributions 	{"ldm", .p.Bits.KernelOnly = 1},
302bb611c8fSApple OSS Distributions 	{"com.apple.System.boot-nonce", .p.Bits.KernelOnly = 1},
303bb611c8fSApple OSS Distributions 	{"com.apple.System.sep.art", .p.Bits.KernelOnly = 1},
304bb611c8fSApple OSS Distributions 	{"darkboot", .p.Bits.UserWrite = 1},
305bb611c8fSApple OSS Distributions 	{"nonce-seeds", .p.Bits.KernelOnly = 1},
306bb611c8fSApple OSS Distributions #endif /* !defined(__x86_64__) */
307aca3beaaSApple OSS Distributions 	// Variables used for testing permissions
308aca3beaaSApple OSS Distributions 	{"testSysReadHidden", .p.Bits.SystemReadHidden = 1},
309aca3beaaSApple OSS Distributions 	{"testKernelOnly", .p.Bits.KernelOnly = 1},
310aca3beaaSApple OSS Distributions 	{"testResetOnlyDel", .p.Bits.ResetNVRAMOnlyDelete = 1},
311aca3beaaSApple OSS Distributions 	{"testNeverDel", .p.Bits.NeverAllowedToDelete = 1},
312aca3beaaSApple OSS Distributions 	{"testUserWrite", .p.Bits.UserWrite = 1},
313aca3beaaSApple OSS Distributions 	{"testRootReq", .p.Bits.RootRequired = 1},
31494d3b452SApple OSS Distributions 	{"reclaim-int", .p.Bits.InternalOnly = 1},
315bb611c8fSApple OSS Distributions 	{nullptr, {.Bits.FullAccess = 1}} // Default access
316bb611c8fSApple OSS Distributions };
317bb611c8fSApple OSS Distributions 
318aca3beaaSApple OSS Distributions typedef struct {
319aca3beaaSApple OSS Distributions 	const uint8_t checkOp;
320aca3beaaSApple OSS Distributions 	const uuid_t  *varGuid;
321aca3beaaSApple OSS Distributions 	const char    *varName;
322aca3beaaSApple OSS Distributions 	const char    *varEntitlement;
323aca3beaaSApple OSS Distributions } VariableEntitlementEntry;
324aca3beaaSApple OSS Distributions 
325aca3beaaSApple OSS Distributions // variable-guid pair entries that require entitlement check to do specified nvram operations
326aca3beaaSApple OSS Distributions static const
327aca3beaaSApple OSS Distributions VariableEntitlementEntry gVariableEntitlements[] = {
3281031c584SApple OSS Distributions 	{ENT_MOD_RST, &gAppleNVRAMGuid, "ownership-warning", "com.apple.private.iokit.ddl-write"},
3291031c584SApple OSS Distributions 	{ENT_MOD, &gAppleSystemVariableGuid, "BluetoothInfo", "com.apple.private.iokit.nvram-bluetooth"},
3301031c584SApple OSS Distributions 	{ENT_MOD, &gAppleSystemVariableGuid, "BluetoothUHEDevices", "com.apple.private.iokit.nvram-bluetooth"},
3311031c584SApple OSS Distributions 	{ENT_MOD, &gAppleNVRAMGuid, "bluetoothExternalDongleFailed", "com.apple.private.iokit.nvram-bluetooth"},
3321031c584SApple OSS Distributions 	{ENT_MOD, &gAppleNVRAMGuid, "bluetoothInternalControllerInfo", "com.apple.private.iokit.nvram-bluetooth"},
33394d3b452SApple OSS Distributions 	{ENT_RD, &gAppleSystemVariableGuid, "current-network", "com.apple.private.security.nvram.wifi-psks"},
33494d3b452SApple OSS Distributions 	{ENT_RD, &gAppleWifiGuid, "current-network", "com.apple.private.security.nvram.wifi-psks"},
33594d3b452SApple OSS Distributions 	{ENT_RD, &gAppleSystemVariableGuid, "preferred-networks", "com.apple.private.security.nvram.wifi-psks"},
33694d3b452SApple OSS Distributions 	{ENT_RD, &gAppleWifiGuid, "preferred-networks", "com.apple.private.security.nvram.wifi-psks"},
33794d3b452SApple OSS Distributions 	{ENT_RD, &gAppleSystemVariableGuid, "preferred-count", "com.apple.private.security.nvram.wifi-psks"},
33894d3b452SApple OSS Distributions 	{ENT_RD, &gAppleWifiGuid, "preferred-count", "com.apple.private.security.nvram.wifi-psks"},
3391031c584SApple OSS Distributions 	// Variables used for testing entitlement
3401031c584SApple OSS Distributions 	{ENT_MOD_RST, &gAppleNVRAMGuid, "testEntModRst", "com.apple.private.iokit.testEntModRst"},
3411031c584SApple OSS Distributions 	{ENT_MOD_RST, &gAppleSystemVariableGuid, "testEntModRstSys", "com.apple.private.iokit.testEntModRst"},
3421031c584SApple OSS Distributions 	{ENT_RST, &gAppleNVRAMGuid, "testEntRst", "com.apple.private.iokit.testEntRst"},
3431031c584SApple OSS Distributions 	{ENT_RST, &gAppleSystemVariableGuid, "testEntRstSys", "com.apple.private.iokit.testEntRst"},
3441031c584SApple OSS Distributions 	{ENT_RD, &gAppleNVRAMGuid, "testEntRd", "com.apple.private.iokit.testEntRd"},
3451031c584SApple OSS Distributions 	{ENT_RD, &gAppleSystemVariableGuid, "testEntRdSys", "com.apple.private.iokit.testEntRd"},
3461031c584SApple OSS Distributions 	{ENT_DEL, &gAppleNVRAMGuid, "testEntDel", "com.apple.private.iokit.testEntDel"},
3471031c584SApple OSS Distributions 	{ENT_DEL, &gAppleSystemVariableGuid, "testEntDelSys", "com.apple.private.iokit.testEntDel"},
348aca3beaaSApple OSS Distributions 	{0, &UUID_NULL, nullptr, nullptr}
349aca3beaaSApple OSS Distributions };
350aca3beaaSApple OSS Distributions 
351e7776783SApple OSS Distributions static NVRAMPartitionType
getPartitionTypeForGUID(const uuid_t guid)3525c2921b0SApple OSS Distributions getPartitionTypeForGUID(const uuid_t guid)
353e7776783SApple OSS Distributions {
3545c2921b0SApple OSS Distributions 	if (uuid_compare(guid, gAppleSystemVariableGuid) == 0) {
355e7776783SApple OSS Distributions 		return kIONVRAMPartitionSystem;
356e7776783SApple OSS Distributions 	} else {
3575c2921b0SApple OSS Distributions 		return kIONVRAMPartitionCommon;
358e7776783SApple OSS Distributions 	}
359e7776783SApple OSS Distributions }
360e7776783SApple OSS Distributions 
361bb611c8fSApple OSS Distributions static IONVRAMVariableType
getVariableType(const char * propName)362bb611c8fSApple OSS Distributions getVariableType(const char *propName)
363bb611c8fSApple OSS Distributions {
364bb611c8fSApple OSS Distributions 	const VariableTypeEntry *entry;
365bb611c8fSApple OSS Distributions 
366bb611c8fSApple OSS Distributions 	entry = gVariableTypes;
367bb611c8fSApple OSS Distributions 	while (entry->name != nullptr) {
368bb611c8fSApple OSS Distributions 		if (strcmp(entry->name, propName) == 0) {
369bb611c8fSApple OSS Distributions 			break;
370bb611c8fSApple OSS Distributions 		}
371bb611c8fSApple OSS Distributions 		entry++;
372bb611c8fSApple OSS Distributions 	}
373bb611c8fSApple OSS Distributions 
374bb611c8fSApple OSS Distributions 	return entry->type;
375bb611c8fSApple OSS Distributions }
376bb611c8fSApple OSS Distributions 
377bb611c8fSApple OSS Distributions static IONVRAMVariableType
getVariableType(const OSSymbol * propSymbol)378bb611c8fSApple OSS Distributions getVariableType(const OSSymbol *propSymbol)
379bb611c8fSApple OSS Distributions {
380bb611c8fSApple OSS Distributions 	return getVariableType(propSymbol->getCStringNoCopy());
381bb611c8fSApple OSS Distributions }
382bb611c8fSApple OSS Distributions 
383bb611c8fSApple OSS Distributions static VariablePermission
getVariablePermission(const char * propName)384bb611c8fSApple OSS Distributions getVariablePermission(const char *propName)
385bb611c8fSApple OSS Distributions {
386bb611c8fSApple OSS Distributions 	const VariablePermissionEntry *entry;
387bb611c8fSApple OSS Distributions 
388bb611c8fSApple OSS Distributions 	entry = gVariablePermissions;
389bb611c8fSApple OSS Distributions 	while (entry->name != nullptr) {
390bb611c8fSApple OSS Distributions 		if (strcmp(entry->name, propName) == 0) {
391bb611c8fSApple OSS Distributions 			break;
392bb611c8fSApple OSS Distributions 		}
393bb611c8fSApple OSS Distributions 		entry++;
394bb611c8fSApple OSS Distributions 	}
395bb611c8fSApple OSS Distributions 
396bb611c8fSApple OSS Distributions 	return entry->p;
397bb611c8fSApple OSS Distributions }
398bb611c8fSApple OSS Distributions 
399bb611c8fSApple OSS Distributions static bool
variableInAllowList(const char * varName)400bb611c8fSApple OSS Distributions variableInAllowList(const char *varName)
401bb611c8fSApple OSS Distributions {
402bb611c8fSApple OSS Distributions 	unsigned int i = 0;
40394d3b452SApple OSS Distributions 	const char * const *list = gInternalBuild ? gNVRAMSystemListInternal : gNVRAMSystemList;
404bb611c8fSApple OSS Distributions 
40594d3b452SApple OSS Distributions 	while (list[i] != nullptr) {
40694d3b452SApple OSS Distributions 		if (strcmp(varName, list[i]) == 0) {
407bb611c8fSApple OSS Distributions 			return true;
408bb611c8fSApple OSS Distributions 		}
409bb611c8fSApple OSS Distributions 		i++;
410bb611c8fSApple OSS Distributions 	}
411bb611c8fSApple OSS Distributions 
412bb611c8fSApple OSS Distributions 	return false;
413bb611c8fSApple OSS Distributions }
414bb611c8fSApple OSS Distributions 
415bb611c8fSApple OSS Distributions static bool
verifyWriteSizeLimit(const uuid_t varGuid,const char * variableName,size_t propDataSize)4165c2921b0SApple OSS Distributions verifyWriteSizeLimit(const uuid_t varGuid, const char *variableName, size_t propDataSize)
417bb611c8fSApple OSS Distributions {
418bb611c8fSApple OSS Distributions 	if (variableInAllowList(variableName)) {
419*8d741a5dSApple OSS Distributions 		return propDataSize <= BOOT_LINE_LENGTH;
420bb611c8fSApple OSS Distributions 	}
421bb611c8fSApple OSS Distributions 
422bb611c8fSApple OSS Distributions 	return true;
423bb611c8fSApple OSS Distributions }
424bb611c8fSApple OSS Distributions 
425e6231be0SApple OSS Distributions #if defined(DEBUG) || defined(DEVELOPMENT)
426e6231be0SApple OSS Distributions static const char *
getNVRAMOpString(IONVRAMOperation op)427e6231be0SApple OSS Distributions getNVRAMOpString(IONVRAMOperation op)
428e6231be0SApple OSS Distributions {
429e6231be0SApple OSS Distributions 	switch (op) {
430e6231be0SApple OSS Distributions 	case kIONVRAMOperationRead:
431e6231be0SApple OSS Distributions 		return "Read";
432e6231be0SApple OSS Distributions 	case kIONVRAMOperationWrite:
433e6231be0SApple OSS Distributions 		return "Write";
434e6231be0SApple OSS Distributions 	case kIONVRAMOperationDelete:
435e6231be0SApple OSS Distributions 		return "Delete";
436e6231be0SApple OSS Distributions 	case kIONVRAMOperationObliterate:
437e6231be0SApple OSS Distributions 		return "Obliterate";
438e6231be0SApple OSS Distributions 	case kIONVRAMOperationReset:
439e6231be0SApple OSS Distributions 		return "Reset";
440e6231be0SApple OSS Distributions 	case kIONVRAMOperationInit:
441e6231be0SApple OSS Distributions 		return "Init";
442e6231be0SApple OSS Distributions 	default:
443e6231be0SApple OSS Distributions 		return "Unknown";
444e6231be0SApple OSS Distributions 	}
445e6231be0SApple OSS Distributions }
446e6231be0SApple OSS Distributions #endif
447e6231be0SApple OSS Distributions 
448bb611c8fSApple OSS Distributions /*
449bb611c8fSApple OSS Distributions  * Parse a variable name of the form "GUID:name".
450bb611c8fSApple OSS Distributions  * If the name cannot be parsed, substitute the Apple global variable GUID.
451bb611c8fSApple OSS Distributions  * Returns TRUE if a GUID was found in the name, FALSE otherwise.
452bb611c8fSApple OSS Distributions  * The guidResult and nameResult arguments may be nullptr if you just want
453bb611c8fSApple OSS Distributions  * to check the format of the string.
454bb611c8fSApple OSS Distributions  */
455bb611c8fSApple OSS Distributions static bool
parseVariableName(const char * key,uuid_t * guidResult,const char ** nameResult)456bb611c8fSApple OSS Distributions parseVariableName(const char *key, uuid_t *guidResult, const char **nameResult)
457bb611c8fSApple OSS Distributions {
458bb611c8fSApple OSS Distributions 	uuid_string_t temp    = {0};
459bb611c8fSApple OSS Distributions 	size_t        keyLen  = strlen(key);
460e6231be0SApple OSS Distributions 	bool          ok      = false;
461bb611c8fSApple OSS Distributions 	const char    *name   = key;
462bb611c8fSApple OSS Distributions 	uuid_t        guid;
463bb611c8fSApple OSS Distributions 
464bb611c8fSApple OSS Distributions 	if (keyLen > sizeof(temp)) {
465bb611c8fSApple OSS Distributions 		// check for at least UUID + ":" + more
466bb611c8fSApple OSS Distributions 		memcpy(temp, key, sizeof(temp) - 1);
467bb611c8fSApple OSS Distributions 
468bb611c8fSApple OSS Distributions 		if ((uuid_parse(temp, guid) == 0) &&
469bb611c8fSApple OSS Distributions 		    (key[sizeof(temp) - 1] == ':')) {
470bb611c8fSApple OSS Distributions 			name = key + sizeof(temp);
471e6231be0SApple OSS Distributions 			ok     = true;
472bb611c8fSApple OSS Distributions 		}
473bb611c8fSApple OSS Distributions 	}
474bb611c8fSApple OSS Distributions 
475bb611c8fSApple OSS Distributions 	if (guidResult) {
476e6231be0SApple OSS Distributions 		ok ? uuid_copy(*guidResult, guid) : uuid_copy(*guidResult, gAppleNVRAMGuid);
477bb611c8fSApple OSS Distributions 	}
478bb611c8fSApple OSS Distributions 	if (nameResult) {
479bb611c8fSApple OSS Distributions 		*nameResult = name;
480bb611c8fSApple OSS Distributions 	}
481bb611c8fSApple OSS Distributions 
4825c2921b0SApple OSS Distributions 	return ok;
483bb611c8fSApple OSS Distributions }
484bb611c8fSApple OSS Distributions 
485e6231be0SApple OSS Distributions static bool
parseVariableName(const OSSymbol * key,uuid_t * guidResult,const char ** nameResult)486aca3beaaSApple OSS Distributions parseVariableName(const OSSymbol *key, uuid_t *guidResult, const char **nameResult)
487aca3beaaSApple OSS Distributions {
488aca3beaaSApple OSS Distributions 	return parseVariableName(key->getCStringNoCopy(), guidResult, nameResult);
489aca3beaaSApple OSS Distributions }
490aca3beaaSApple OSS Distributions 
491aca3beaaSApple OSS Distributions /**
492aca3beaaSApple OSS Distributions  * @brief Translates(if needed) varGuid and stores it in destGuid
493aca3beaaSApple OSS Distributions  *
494aca3beaaSApple OSS Distributions  * @param varGuid       guid to translate
495aca3beaaSApple OSS Distributions  * @param variableName  variable name attached to the guid
496aca3beaaSApple OSS Distributions  * @param destGuid      translated guid is saved here
497aca3beaaSApple OSS Distributions  * @param systemActive  boolean to indicate if it has system partition size > 0
498aca3beaaSApple OSS Distributions  */
499aca3beaaSApple OSS Distributions static void
translateGUID(const uuid_t varGuid,const char * variableName,uuid_t destGuid,bool systemActive)500aca3beaaSApple OSS Distributions translateGUID(const uuid_t varGuid, const char *variableName, uuid_t destGuid, bool systemActive)
501aca3beaaSApple OSS Distributions {
502aca3beaaSApple OSS Distributions 	if (varGuid == nullptr || variableName == nullptr || destGuid == nullptr) {
503aca3beaaSApple OSS Distributions 		DEBUG_ERROR("nullptr passed as an argument\n");
504aca3beaaSApple OSS Distributions 		return;
505aca3beaaSApple OSS Distributions 	}
506aca3beaaSApple OSS Distributions 
507aca3beaaSApple OSS Distributions 	bool systemGuid = uuid_compare(varGuid, gAppleSystemVariableGuid) == 0;
508aca3beaaSApple OSS Distributions 
509aca3beaaSApple OSS Distributions 	if (systemActive) {
510aca3beaaSApple OSS Distributions 		if (variableInAllowList(variableName)) {
511aca3beaaSApple OSS Distributions 			DEBUG_INFO("Using system GUID due to allow list\n");
512aca3beaaSApple OSS Distributions 			uuid_copy(destGuid, gAppleSystemVariableGuid);
513aca3beaaSApple OSS Distributions 		} else if (systemGuid) {
514aca3beaaSApple OSS Distributions 			DEBUG_INFO("System GUID used\n");
515aca3beaaSApple OSS Distributions 			uuid_copy(destGuid, gAppleSystemVariableGuid);
516aca3beaaSApple OSS Distributions 		} else {
517aca3beaaSApple OSS Distributions 			DEBUG_INFO("Use given guid\n");
518aca3beaaSApple OSS Distributions 			uuid_copy(destGuid, varGuid);
519aca3beaaSApple OSS Distributions 		}
520aca3beaaSApple OSS Distributions 	} else if (systemGuid) {
521aca3beaaSApple OSS Distributions 		DEBUG_INFO("Overriding to Apple guid\n");
522aca3beaaSApple OSS Distributions 		uuid_copy(destGuid, gAppleNVRAMGuid);
523aca3beaaSApple OSS Distributions 	} else {
524aca3beaaSApple OSS Distributions 		DEBUG_INFO("Use given guid\n");
525aca3beaaSApple OSS Distributions 		uuid_copy(destGuid, varGuid);
526aca3beaaSApple OSS Distributions 	}
527aca3beaaSApple OSS Distributions }
528aca3beaaSApple OSS Distributions 
529aca3beaaSApple OSS Distributions /**
530aca3beaaSApple OSS Distributions  * @brief Checks if the variable-guid(translated) pair is present in gVariableEntitlements and if so,
531aca3beaaSApple OSS Distributions  *        does it have the required entitlement for the NVRAM operation passed in
532aca3beaaSApple OSS Distributions  *
533aca3beaaSApple OSS Distributions  * @param varGuid       guid for the variable to be checked, this gets translated by translateGUID
534aca3beaaSApple OSS Distributions  * @param varName       variable name
535aca3beaaSApple OSS Distributions  * @param op            NVRAM operation
536aca3beaaSApple OSS Distributions  * @param systemActive  used to pass into translateGUID to get the correct guid to check against
537aca3beaaSApple OSS Distributions  * @param veChecked     if variable entitlement is checked, this is set to true
538aca3beaaSApple OSS Distributions  * @return true         if variable wasn't present in gVariableEntitlements,
539aca3beaaSApple OSS Distributions  *                      entitlement check wasn't required for operation passed in,
540aca3beaaSApple OSS Distributions  *                      or if entitlement check returned true
541aca3beaaSApple OSS Distributions  * @return false        if varName/varGuid/veChecked was NULL or if entitlement check returned false
542aca3beaaSApple OSS Distributions  */
543aca3beaaSApple OSS Distributions static bool
verifyVarEntitlement(const uuid_t varGuid,const char * varName,IONVRAMOperation op,bool systemActive,bool * veChecked)544aca3beaaSApple OSS Distributions verifyVarEntitlement(const uuid_t varGuid, const char *varName, IONVRAMOperation op, bool systemActive, bool *veChecked)
545aca3beaaSApple OSS Distributions {
546aca3beaaSApple OSS Distributions 	if (varGuid == nullptr || varName == nullptr || veChecked == nullptr) {
547aca3beaaSApple OSS Distributions 		DEBUG_ERROR("nullptr passed as an argument\n");
548aca3beaaSApple OSS Distributions 		return false;
549aca3beaaSApple OSS Distributions 	}
550aca3beaaSApple OSS Distributions 
551aca3beaaSApple OSS Distributions 	uuid_t translatedGuid;
552aca3beaaSApple OSS Distributions 	const VariableEntitlementEntry *entry;
553aca3beaaSApple OSS Distributions 	*veChecked = false;
554aca3beaaSApple OSS Distributions 
5551031c584SApple OSS Distributions 	translateGUID(varGuid, varName, translatedGuid, systemActive);
5561031c584SApple OSS Distributions 
557aca3beaaSApple OSS Distributions 	entry = gVariableEntitlements;
558aca3beaaSApple OSS Distributions 	while ((entry != nullptr) && (entry->varName != nullptr)) {
559aca3beaaSApple OSS Distributions 		if ((strcmp(entry->varName, varName) == 0) && (uuid_compare(translatedGuid, *(entry->varGuid)) == 0)) {
560aca3beaaSApple OSS Distributions 			// check if task entitlement check is required for this operation
561aca3beaaSApple OSS Distributions 			if (entry->checkOp & (1 << op)) {
562aca3beaaSApple OSS Distributions 				*veChecked = true;
5631031c584SApple OSS Distributions 				DEBUG_INFO("Checking entitlement %s for %s for operation %s\n", entry->varEntitlement, varName, getNVRAMOpString(op));
564aca3beaaSApple OSS Distributions 				return IOCurrentTaskHasEntitlement(entry->varEntitlement);
565aca3beaaSApple OSS Distributions 			}
566aca3beaaSApple OSS Distributions 			break;
567aca3beaaSApple OSS Distributions 		}
568aca3beaaSApple OSS Distributions 		entry++;
569aca3beaaSApple OSS Distributions 	}
570aca3beaaSApple OSS Distributions 
571aca3beaaSApple OSS Distributions 	return true;
572aca3beaaSApple OSS Distributions }
573aca3beaaSApple OSS Distributions 
574aca3beaaSApple OSS Distributions static bool
kernelOnlyVar(const uuid_t varGuid,const char * varName)5751031c584SApple OSS Distributions kernelOnlyVar(const uuid_t varGuid, const char *varName)
5761031c584SApple OSS Distributions {
5771031c584SApple OSS Distributions 	if (strncmp(varName, KERNEL_ONLY_VAR_NAME_PREFIX, sizeof(KERNEL_ONLY_VAR_NAME_PREFIX) - 1) == 0) {
5781031c584SApple OSS Distributions 		return true;
5791031c584SApple OSS Distributions 	}
5801031c584SApple OSS Distributions 
5811031c584SApple OSS Distributions 	return false;
5821031c584SApple OSS Distributions }
5831031c584SApple OSS Distributions 
5841031c584SApple OSS Distributions static bool
verifyPermission(IONVRAMOperation op,const uuid_t varGuid,const char * varName,const bool systemActive)585aca3beaaSApple OSS Distributions verifyPermission(IONVRAMOperation op, const uuid_t varGuid, const char *varName, const bool systemActive)
586aca3beaaSApple OSS Distributions {
587aca3beaaSApple OSS Distributions 	VariablePermission perm;
588aca3beaaSApple OSS Distributions 	bool kernel, varEntitled, writeEntitled = false, readEntitled = false, allowList, systemGuid = false, systemEntitled = false, systemInternalEntitled = false, systemAllow, systemReadHiddenAllow = false;
589aca3beaaSApple OSS Distributions 	bool admin = false;
590aca3beaaSApple OSS Distributions 	bool ok = false;
591aca3beaaSApple OSS Distributions 
592aca3beaaSApple OSS Distributions 	if (verifyVarEntitlement(varGuid, varName, op, systemActive, &varEntitled) == false) {
593aca3beaaSApple OSS Distributions 		goto exit;
594aca3beaaSApple OSS Distributions 	}
595aca3beaaSApple OSS Distributions 
596aca3beaaSApple OSS Distributions 	perm = getVariablePermission(varName);
597aca3beaaSApple OSS Distributions 
598aca3beaaSApple OSS Distributions 	kernel = current_task() == kernel_task;
599aca3beaaSApple OSS Distributions 
6001031c584SApple OSS Distributions 	if (perm.Bits.KernelOnly || kernelOnlyVar(varGuid, varName)) {
601aca3beaaSApple OSS Distributions 		DEBUG_INFO("KernelOnly access for %s, kernel=%d\n", varName, kernel);
602aca3beaaSApple OSS Distributions 		ok = kernel;
603aca3beaaSApple OSS Distributions 		goto exit;
604aca3beaaSApple OSS Distributions 	}
605aca3beaaSApple OSS Distributions 
60694d3b452SApple OSS Distributions 	if (perm.Bits.InternalOnly && !gInternalBuild) {
60794d3b452SApple OSS Distributions 		DEBUG_INFO("InternalOnly access for %s, gInternalBuild=%d\n", varName, gInternalBuild);
60894d3b452SApple OSS Distributions 		goto exit;
60994d3b452SApple OSS Distributions 	}
61094d3b452SApple OSS Distributions 
611aca3beaaSApple OSS Distributions 	allowList              = variableInAllowList(varName);
612aca3beaaSApple OSS Distributions 	systemGuid             = uuid_compare(varGuid, gAppleSystemVariableGuid) == 0;
613aca3beaaSApple OSS Distributions 	admin                  = IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege) == kIOReturnSuccess;
614aca3beaaSApple OSS Distributions 	writeEntitled          = IOCurrentTaskHasEntitlement(kIONVRAMWriteAccessKey);
615aca3beaaSApple OSS Distributions 	readEntitled           = IOCurrentTaskHasEntitlement(kIONVRAMReadAccessKey);
616aca3beaaSApple OSS Distributions 	systemEntitled         = IOCurrentTaskHasEntitlement(kIONVRAMSystemAllowKey);
617aca3beaaSApple OSS Distributions 	systemInternalEntitled = IOCurrentTaskHasEntitlement(kIONVRAMSystemInternalAllowKey);
618aca3beaaSApple OSS Distributions 	systemReadHiddenAllow  = IOCurrentTaskHasEntitlement(kIONVRAMSystemHiddenAllowKey);
619aca3beaaSApple OSS Distributions 
620aca3beaaSApple OSS Distributions 	systemAllow = systemEntitled || (systemInternalEntitled && gInternalBuild) || kernel;
621aca3beaaSApple OSS Distributions 
622aca3beaaSApple OSS Distributions 	switch (op) {
623aca3beaaSApple OSS Distributions 	case kIONVRAMOperationRead:
624aca3beaaSApple OSS Distributions 		if (systemGuid && perm.Bits.SystemReadHidden) {
625aca3beaaSApple OSS Distributions 			ok = systemReadHiddenAllow;
6261031c584SApple OSS Distributions 		} else if (kernel || admin || readEntitled || perm.Bits.FullAccess || varEntitled) {
627aca3beaaSApple OSS Distributions 			ok = true;
628aca3beaaSApple OSS Distributions 		}
629aca3beaaSApple OSS Distributions 		break;
630aca3beaaSApple OSS Distributions 
631aca3beaaSApple OSS Distributions 	case kIONVRAMOperationWrite:
632aca3beaaSApple OSS Distributions 		if (kernel || perm.Bits.UserWrite || admin || writeEntitled || varEntitled) {
633aca3beaaSApple OSS Distributions 			if (systemGuid) {
634aca3beaaSApple OSS Distributions 				if (allowList) {
635aca3beaaSApple OSS Distributions 					if (!systemAllow) {
636aca3beaaSApple OSS Distributions 						DEBUG_ERROR("Allowed write to system region when NOT entitled for %s\n", varName);
637aca3beaaSApple OSS Distributions 					}
6381031c584SApple OSS Distributions 				} else if (varEntitled) {
6391031c584SApple OSS Distributions 					DEBUG_INFO("Allowed write to system region using variable specific entitlement for %s\n", varName);
640aca3beaaSApple OSS Distributions 				} else if (!systemAllow) {
641aca3beaaSApple OSS Distributions 					DEBUG_ERROR("Not entitled for system region writes for %s\n", varName);
642aca3beaaSApple OSS Distributions 					break;
643aca3beaaSApple OSS Distributions 				}
644aca3beaaSApple OSS Distributions 			}
645aca3beaaSApple OSS Distributions 			ok = true;
646aca3beaaSApple OSS Distributions 		}
647aca3beaaSApple OSS Distributions 		break;
648aca3beaaSApple OSS Distributions 
649aca3beaaSApple OSS Distributions 	case kIONVRAMOperationDelete:
650aca3beaaSApple OSS Distributions 	case kIONVRAMOperationObliterate:
651aca3beaaSApple OSS Distributions 	case kIONVRAMOperationReset:
652aca3beaaSApple OSS Distributions 		if (perm.Bits.NeverAllowedToDelete) {
653aca3beaaSApple OSS Distributions 			DEBUG_INFO("Never allowed to delete %s\n", varName);
654aca3beaaSApple OSS Distributions 			break;
655aca3beaaSApple OSS Distributions 		} else if ((op == kIONVRAMOperationObliterate) && perm.Bits.ResetNVRAMOnlyDelete) {
656aca3beaaSApple OSS Distributions 			DEBUG_INFO("Not allowed to obliterate %s\n", varName);
657aca3beaaSApple OSS Distributions 			break;
658aca3beaaSApple OSS Distributions 		} else if ((op == kIONVRAMOperationDelete) && perm.Bits.ResetNVRAMOnlyDelete) {
659aca3beaaSApple OSS Distributions 			DEBUG_INFO("Only allowed to delete %s via NVRAM reset\n", varName);
660aca3beaaSApple OSS Distributions 			break;
661aca3beaaSApple OSS Distributions 		}
662aca3beaaSApple OSS Distributions 
663aca3beaaSApple OSS Distributions 		if (kernel || perm.Bits.UserWrite || admin || writeEntitled || varEntitled) {
664aca3beaaSApple OSS Distributions 			if (systemGuid) {
665aca3beaaSApple OSS Distributions 				if (allowList) {
666aca3beaaSApple OSS Distributions 					if (!systemAllow) {
667aca3beaaSApple OSS Distributions 						DEBUG_ERROR("Allowed delete to system region when NOT entitled for %s\n", varName);
668aca3beaaSApple OSS Distributions 					}
6691031c584SApple OSS Distributions 				} else if (varEntitled) {
6701031c584SApple OSS Distributions 					DEBUG_INFO("Allowed delete to system region using variable specific entitlement for %s\n", varName);
671aca3beaaSApple OSS Distributions 				} else if (!systemAllow) {
672aca3beaaSApple OSS Distributions 					DEBUG_ERROR("Not entitled for system region deletes for %s\n", varName);
673aca3beaaSApple OSS Distributions 					break;
674aca3beaaSApple OSS Distributions 				}
675aca3beaaSApple OSS Distributions 			}
676aca3beaaSApple OSS Distributions 			ok = true;
677aca3beaaSApple OSS Distributions 		}
678aca3beaaSApple OSS Distributions 		break;
679aca3beaaSApple OSS Distributions 
680aca3beaaSApple OSS Distributions 	case kIONVRAMOperationInit:
681aca3beaaSApple OSS Distributions 		break;
682aca3beaaSApple OSS Distributions 	}
683aca3beaaSApple OSS Distributions 
684aca3beaaSApple OSS Distributions exit:
68594d3b452SApple OSS Distributions 	DEBUG_INFO("Permission for %s of %s %s: I=%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",
68694d3b452SApple OSS Distributions 	    gInternalBuild, kernel, admin, writeEntitled, readEntitled, systemGuid, systemEntitled, systemInternalEntitled, systemReadHiddenAllow, perm.Bits.UserWrite, varEntitled);
687aca3beaaSApple OSS Distributions 
688aca3beaaSApple OSS Distributions 	return ok;
689aca3beaaSApple OSS Distributions }
690aca3beaaSApple OSS Distributions 
691aca3beaaSApple OSS Distributions static bool
verifyPermission(IONVRAMOperation op,const OSSymbol * canonicalKey,const bool systemActive)692aca3beaaSApple OSS Distributions verifyPermission(IONVRAMOperation op, const OSSymbol *canonicalKey, const bool systemActive)
693aca3beaaSApple OSS Distributions {
694aca3beaaSApple OSS Distributions 	const char *varName;
695aca3beaaSApple OSS Distributions 	uuid_t varGuid;
696aca3beaaSApple OSS Distributions 
697aca3beaaSApple OSS Distributions 	parseVariableName(canonicalKey->getCStringNoCopy(), &varGuid, &varName);
698aca3beaaSApple OSS Distributions 
699aca3beaaSApple OSS Distributions 	return verifyPermission(op, varGuid, varName, systemActive);
700aca3beaaSApple OSS Distributions }
701aca3beaaSApple OSS Distributions 
702aca3beaaSApple OSS Distributions static bool
skipKey(const OSSymbol * aKey)703e6231be0SApple OSS Distributions skipKey(const OSSymbol *aKey)
704e6231be0SApple OSS Distributions {
7055c2921b0SApple OSS Distributions 	return aKey->isEqualTo(kIORegistryEntryAllowableSetPropertiesKey) ||
7065c2921b0SApple OSS Distributions 	       aKey->isEqualTo(kIORegistryEntryDefaultLockingSetPropertiesKey) ||
7075c2921b0SApple OSS Distributions 	       aKey->isEqualTo(kIOClassNameOverrideKey) ||
708e6231be0SApple OSS Distributions 	       aKey->isEqualTo(kIOBSDNameKey) ||
709e6231be0SApple OSS Distributions 	       aKey->isEqualTo(kIOBSDNamesKey) ||
710e6231be0SApple OSS Distributions 	       aKey->isEqualTo(kIOBSDMajorKey) ||
711e6231be0SApple OSS Distributions 	       aKey->isEqualTo(kIOBSDMinorKey) ||
712e6231be0SApple OSS Distributions 	       aKey->isEqualTo(kIOBSDUnitKey) ||
713e6231be0SApple OSS Distributions 	       aKey->isEqualTo(kIOUserServicePropertiesKey) ||
7141031c584SApple OSS Distributions 	       aKey->isEqualTo(kIOExclaveAssignedKey) ||
715*8d741a5dSApple OSS Distributions 	       aKey->isEqualTo(kIOMatchCategoryKey) ||
716*8d741a5dSApple OSS Distributions 	       aKey->isEqualTo(kIOBusyInterest);
717e6231be0SApple OSS Distributions }
718e6231be0SApple OSS Distributions 
719aca3beaaSApple OSS Distributions static OSSharedPtr<const OSSymbol>
keyWithGuidAndCString(const uuid_t guid,const char * cstring)720aca3beaaSApple OSS Distributions keyWithGuidAndCString(const uuid_t guid, const char * cstring)
721aca3beaaSApple OSS Distributions {
722aca3beaaSApple OSS Distributions 	size_t                      length;
723aca3beaaSApple OSS Distributions 	OSSharedPtr<const OSSymbol> symbolObj;
724aca3beaaSApple OSS Distributions 	char                        *canonicalString;
725aca3beaaSApple OSS Distributions 
726aca3beaaSApple OSS Distributions 	length = sizeof(uuid_string_t) - 1 + sizeof(':') + strlen(cstring) + 1;
727aca3beaaSApple OSS Distributions 
728aca3beaaSApple OSS Distributions 	canonicalString = (char *) IOMallocData(length);
729aca3beaaSApple OSS Distributions 	if (canonicalString == nullptr) {
730aca3beaaSApple OSS Distributions 		return NULL;
731aca3beaaSApple OSS Distributions 	}
732aca3beaaSApple OSS Distributions 
733aca3beaaSApple OSS Distributions 	uuid_unparse(guid, *((uuid_string_t*)canonicalString));
734aca3beaaSApple OSS Distributions 	canonicalString[sizeof(uuid_string_t) - 1] = ':';
735aca3beaaSApple OSS Distributions 
736aca3beaaSApple OSS Distributions 	strlcpy(&canonicalString[sizeof(uuid_string_t)], cstring, length - sizeof(uuid_string_t));
737aca3beaaSApple OSS Distributions 
738aca3beaaSApple OSS Distributions 	symbolObj = OSSymbol::withCString(canonicalString);
739aca3beaaSApple OSS Distributions 	IOFreeData(canonicalString, length);
740aca3beaaSApple OSS Distributions 
741aca3beaaSApple OSS Distributions 	return symbolObj;
742aca3beaaSApple OSS Distributions }
743aca3beaaSApple OSS Distributions 
744aca3beaaSApple OSS Distributions static void
dumpDict(const OSDictionary * dict)745aca3beaaSApple OSS Distributions dumpDict(const OSDictionary *dict)
746aca3beaaSApple OSS Distributions {
747aca3beaaSApple OSS Distributions 	const OSSymbol                    *key;
748aca3beaaSApple OSS Distributions 	OSSharedPtr<OSCollectionIterator> iter;
749aca3beaaSApple OSS Distributions 	unsigned int                      count = 0;
750aca3beaaSApple OSS Distributions 
751aca3beaaSApple OSS Distributions 	iter = OSCollectionIterator::withCollection(dict);
752aca3beaaSApple OSS Distributions 	if (iter == nullptr) {
753aca3beaaSApple OSS Distributions 		DEBUG_ERROR("failed to create iterator\n");
754aca3beaaSApple OSS Distributions 		goto exit;
755aca3beaaSApple OSS Distributions 	}
756aca3beaaSApple OSS Distributions 
757aca3beaaSApple OSS Distributions 	DEBUG_INFO("Dumping dict...\n");
758aca3beaaSApple OSS Distributions 	while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
759aca3beaaSApple OSS Distributions 		count++;
760aca3beaaSApple OSS Distributions 		DEBUG_INFO("%u: %s\n", count, key->getCStringNoCopy());
761aca3beaaSApple OSS Distributions 	}
762aca3beaaSApple OSS Distributions 
763aca3beaaSApple OSS Distributions exit:
764aca3beaaSApple OSS Distributions 	return;
765aca3beaaSApple OSS Distributions }
766e7776783SApple OSS Distributions 
7675c2921b0SApple OSS Distributions // ************************** IODTNVRAMPlatformNotifier ****************************
7685c2921b0SApple OSS Distributions // private IOService based class for passing notifications to IODTNVRAM
769e6231be0SApple OSS Distributions 
7705c2921b0SApple OSS Distributions class IODTNVRAMPlatformNotifier : public IOService
7715c2921b0SApple OSS Distributions {
7725c2921b0SApple OSS Distributions 	OSDeclareDefaultStructors(IODTNVRAMPlatformNotifier)
7735c2921b0SApple OSS Distributions private:
7745c2921b0SApple OSS Distributions 	IODTNVRAM *_provider;
7755c2921b0SApple OSS Distributions 
7765c2921b0SApple OSS Distributions public:
7775c2921b0SApple OSS Distributions 	bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
7785c2921b0SApple OSS Distributions 
7795c2921b0SApple OSS Distributions 	virtual IOReturn callPlatformFunction( const OSSymbol * functionName,
7805c2921b0SApple OSS Distributions 	    bool waitForFunction,
7815c2921b0SApple OSS Distributions 	    void *param1, void *param2,
7825c2921b0SApple OSS Distributions 	    void *param3, void *param4 ) APPLE_KEXT_OVERRIDE;
7835c2921b0SApple OSS Distributions };
7845c2921b0SApple OSS Distributions 
OSDefineMetaClassAndStructors(IODTNVRAMPlatformNotifier,IOService)7855c2921b0SApple OSS Distributions OSDefineMetaClassAndStructors(IODTNVRAMPlatformNotifier, IOService)
7865c2921b0SApple OSS Distributions 
7875c2921b0SApple OSS Distributions bool
7885c2921b0SApple OSS Distributions IODTNVRAMPlatformNotifier::start(IOService * provider)
7895c2921b0SApple OSS Distributions {
7905c2921b0SApple OSS Distributions 	OSSharedPtr<OSSerializer> serializer;
7915c2921b0SApple OSS Distributions 	OSSharedPtr<OSNumber> value = OSNumber::withNumber(1000, 32);
7925c2921b0SApple OSS Distributions 
7935c2921b0SApple OSS Distributions 	_provider = OSDynamicCast(IODTNVRAM, provider);
7945c2921b0SApple OSS Distributions 	require(_provider != nullptr, error);
7955c2921b0SApple OSS Distributions 
7965c2921b0SApple OSS Distributions 	setProperty(gIOPlatformWakeActionKey, value.get());
7975c2921b0SApple OSS Distributions 
7985c2921b0SApple OSS Distributions 	require(super::start(provider), error);
7995c2921b0SApple OSS Distributions 
8005c2921b0SApple OSS Distributions 	registerService();
8015c2921b0SApple OSS Distributions 
8025c2921b0SApple OSS Distributions 	return true;
8035c2921b0SApple OSS Distributions 
8045c2921b0SApple OSS Distributions error:
8055c2921b0SApple OSS Distributions 	stop(provider);
8065c2921b0SApple OSS Distributions 
8075c2921b0SApple OSS Distributions 	return false;
8085c2921b0SApple OSS Distributions }
8095c2921b0SApple OSS Distributions 
8105c2921b0SApple OSS Distributions #include <IOKit/IOHibernatePrivate.h>
8115c2921b0SApple OSS Distributions #include <IOKit/pwr_mgt/RootDomain.h>
8125c2921b0SApple OSS Distributions static const OSSharedPtr<const OSSymbol> gIOHibernateStateKey = OSSymbol::withCString(kIOHibernateStateKey);
8135c2921b0SApple OSS Distributions 
8145c2921b0SApple OSS Distributions static uint32_t
hibernateState(void)8155c2921b0SApple OSS Distributions hibernateState(void)
8165c2921b0SApple OSS Distributions {
8175c2921b0SApple OSS Distributions 	OSSharedPtr<OSData> data = OSDynamicPtrCast<OSData>(IOService::getPMRootDomain()->copyProperty(gIOHibernateStateKey.get()->getCStringNoCopy()));
8185c2921b0SApple OSS Distributions 	uint32_t hibernateState = 0;
8195c2921b0SApple OSS Distributions 	if ((data != NULL) && (data->getLength() == sizeof(hibernateState))) {
8205c2921b0SApple OSS Distributions 		memcpy(&hibernateState, data->getBytesNoCopy(), sizeof(hibernateState));
8215c2921b0SApple OSS Distributions 	}
8225c2921b0SApple OSS Distributions 	return hibernateState;
8235c2921b0SApple OSS Distributions }
8245c2921b0SApple OSS Distributions 
8255c2921b0SApple OSS Distributions IOReturn
callPlatformFunction(const OSSymbol * functionName,bool waitForFunction,void * param1,void * param2,void * param3,void * param4)8265c2921b0SApple OSS Distributions IODTNVRAMPlatformNotifier::callPlatformFunction( const OSSymbol * functionName,
8275c2921b0SApple OSS Distributions     bool waitForFunction,
8285c2921b0SApple OSS Distributions     void *param1, void *param2,
8295c2921b0SApple OSS Distributions     void *param3, void *param4 )
8305c2921b0SApple OSS Distributions {
8315c2921b0SApple OSS Distributions 	if ((functionName == gIOPlatformWakeActionKey) &&
8325c2921b0SApple OSS Distributions 	    (hibernateState() == kIOHibernateStateWakingFromHibernate)) {
8335c2921b0SApple OSS Distributions 		DEBUG_INFO("waking from hibernate\n");
8345c2921b0SApple OSS Distributions 		_provider->reload();
8355c2921b0SApple OSS Distributions 		return kIOReturnSuccess;
8365c2921b0SApple OSS Distributions 	}
8375c2921b0SApple OSS Distributions 
8385c2921b0SApple OSS Distributions 	return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4);
8395c2921b0SApple OSS Distributions }
8405c2921b0SApple OSS Distributions 
8415c2921b0SApple OSS Distributions 
8425c2921b0SApple OSS Distributions // ************************** IODTNVRAMDiags ****************************
8435c2921b0SApple OSS Distributions // private IOService based class for passing notifications to IODTNVRAM
844e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsStatsKey   "Stats"
845e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsInitKey    "Init"
846e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsReadKey    "Read"
847e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsWriteKey   "Write"
848e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsDeleteKey  "Delete"
849e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsNameKey    "Name"
850e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsSizeKey    "Size"
851e6231be0SApple OSS Distributions #define kIODTNVRAMDiagsPresentKey "Present"
852e6231be0SApple OSS Distributions 
853e6231be0SApple OSS Distributions // private IOService based class for publishing diagnostic info for IODTNVRAM
854e6231be0SApple OSS Distributions class IODTNVRAMDiags : public IOService
855e6231be0SApple OSS Distributions {
856e6231be0SApple OSS Distributions 	OSDeclareDefaultStructors(IODTNVRAMDiags)
857e6231be0SApple OSS Distributions private:
858e6231be0SApple OSS Distributions 	IODTNVRAM                 *_provider;
859e6231be0SApple OSS Distributions 	IORWLock                  *_variableLock;
860e6231be0SApple OSS Distributions 	OSSharedPtr<OSDictionary> _stats;
861e6231be0SApple OSS Distributions 
862e6231be0SApple OSS Distributions 	bool serializeStats(void *, OSSerialize * serializer);
863e6231be0SApple OSS Distributions 
864e6231be0SApple OSS Distributions public:
865e7776783SApple OSS Distributions 	bool start(IOService * provider) APPLE_KEXT_OVERRIDE;
866e6231be0SApple OSS Distributions 	void logVariable(NVRAMPartitionType region, IONVRAMOperation op, const char *name, void *data);
867e6231be0SApple OSS Distributions };
868e6231be0SApple OSS Distributions 
OSDefineMetaClassAndStructors(IODTNVRAMDiags,IOService)869e6231be0SApple OSS Distributions OSDefineMetaClassAndStructors(IODTNVRAMDiags, IOService)
870e6231be0SApple OSS Distributions 
871e6231be0SApple OSS Distributions bool
872e7776783SApple OSS Distributions IODTNVRAMDiags::start(IOService * provider)
873e6231be0SApple OSS Distributions {
874e6231be0SApple OSS Distributions 	OSSharedPtr<OSSerializer> serializer;
875e6231be0SApple OSS Distributions 
876aca3beaaSApple OSS Distributions 	_provider = OSDynamicCast(IODTNVRAM, provider);
877aca3beaaSApple OSS Distributions 	require(_provider != nullptr, error);
878aca3beaaSApple OSS Distributions 
879e6231be0SApple OSS Distributions 	require(super::start(provider), error);
880e6231be0SApple OSS Distributions 
881e7776783SApple OSS Distributions 	_variableLock = IORWLockAlloc();
882e7776783SApple OSS Distributions 	require(_variableLock != nullptr, error);
883e6231be0SApple OSS Distributions 
884e6231be0SApple OSS Distributions 	_stats = OSDictionary::withCapacity(1);
885e6231be0SApple OSS Distributions 	require(_stats != nullptr, error);
886e6231be0SApple OSS Distributions 
887e6231be0SApple OSS Distributions 	serializer = OSSerializer::forTarget(this, OSMemberFunctionCast(OSSerializerCallback, this, &IODTNVRAMDiags::serializeStats));
888e6231be0SApple OSS Distributions 	require(serializer != nullptr, error);
889e6231be0SApple OSS Distributions 
890e6231be0SApple OSS Distributions 	setProperty(kIODTNVRAMDiagsStatsKey, serializer.get());
891e6231be0SApple OSS Distributions 
892e6231be0SApple OSS Distributions 	registerService();
893e6231be0SApple OSS Distributions 
894e6231be0SApple OSS Distributions 	return true;
895e6231be0SApple OSS Distributions 
896e6231be0SApple OSS Distributions error:
897e6231be0SApple OSS Distributions 	stop(provider);
898e6231be0SApple OSS Distributions 
899e6231be0SApple OSS Distributions 	return false;
900e6231be0SApple OSS Distributions }
901e6231be0SApple OSS Distributions 
902e6231be0SApple OSS Distributions void
logVariable(NVRAMPartitionType region,IONVRAMOperation op,const char * name,void * data)903e6231be0SApple OSS Distributions IODTNVRAMDiags::logVariable(NVRAMPartitionType region, IONVRAMOperation op, const char *name, void *data)
904e6231be0SApple OSS Distributions {
905e6231be0SApple OSS Distributions 	// "Stats"        : OSDictionary
906e6231be0SApple OSS Distributions 	// - "XX:varName" : OSDictionary, XX is the region value prefix to distinguish which dictionary the variable is in
907e6231be0SApple OSS Distributions 	//   - "Init"     : OSBoolean True/present if variable present at initialization
908e6231be0SApple OSS Distributions 	//   - "Read"     : OSNumber count
909e6231be0SApple OSS Distributions 	//   - "Write"    : OSNumber count
910e6231be0SApple OSS Distributions 	//   - "Delete"   : OSNumber count
911e6231be0SApple OSS Distributions 	//   - "Size"     : OSNumber size, latest size from either init or write
912e6231be0SApple OSS Distributions 	//   - "Present"  : OSBoolean True/False if variable is present or not
913e6231be0SApple OSS Distributions 	char                      *entryKey;
914e6231be0SApple OSS Distributions 	size_t                    entryKeySize;
915e6231be0SApple OSS Distributions 	OSSharedPtr<OSDictionary> existingEntry;
916e6231be0SApple OSS Distributions 	OSSharedPtr<OSNumber>     currentCount;
917e6231be0SApple OSS Distributions 	OSSharedPtr<OSNumber>     varSize;
918e6231be0SApple OSS Distributions 	const char                *opCountKey = nullptr;
919e6231be0SApple OSS Distributions 
920e6231be0SApple OSS Distributions 	entryKeySize = strlen("XX:") + strlen(name) +  1;
921e6231be0SApple OSS Distributions 	entryKey = IONewData(char, entryKeySize);
922e6231be0SApple OSS Distributions 	require(entryKey, exit);
923e6231be0SApple OSS Distributions 
924e6231be0SApple OSS Distributions 	snprintf(entryKey, entryKeySize, "%02X:%s", region, name);
925e6231be0SApple OSS Distributions 
926e6231be0SApple OSS Distributions 	NVRAMWRITELOCK();
927e6231be0SApple OSS Distributions 	existingEntry.reset(OSDynamicCast(OSDictionary, _stats->getObject(entryKey)), OSRetain);
928e6231be0SApple OSS Distributions 
929e6231be0SApple OSS Distributions 	if (existingEntry == nullptr) {
930e6231be0SApple OSS Distributions 		existingEntry = OSDictionary::withCapacity(4);
931e6231be0SApple OSS Distributions 	}
932e6231be0SApple OSS Distributions 
933e6231be0SApple OSS Distributions 	switch (op) {
934e6231be0SApple OSS Distributions 	case kIONVRAMOperationRead:
935e6231be0SApple OSS Distributions 		opCountKey = kIODTNVRAMDiagsReadKey;
936e6231be0SApple OSS Distributions 		if (existingEntry->getObject(kIODTNVRAMDiagsPresentKey) == nullptr) {
937e6231be0SApple OSS Distributions 			existingEntry->setObject(kIODTNVRAMDiagsPresentKey, kOSBooleanFalse);
938e6231be0SApple OSS Distributions 		}
939e6231be0SApple OSS Distributions 		break;
940e6231be0SApple OSS Distributions 	case kIONVRAMOperationWrite:
941e6231be0SApple OSS Distributions 		opCountKey = kIODTNVRAMDiagsWriteKey;
942e6231be0SApple OSS Distributions 		varSize = OSNumber::withNumber((size_t)data, 64);
943e6231be0SApple OSS Distributions 		existingEntry->setObject(kIODTNVRAMDiagsSizeKey, varSize);
944e6231be0SApple OSS Distributions 		existingEntry->setObject(kIODTNVRAMDiagsPresentKey, kOSBooleanTrue);
945e6231be0SApple OSS Distributions 		break;
946e6231be0SApple OSS Distributions 	case kIONVRAMOperationDelete:
947e6231be0SApple OSS Distributions 	case kIONVRAMOperationObliterate:
948e6231be0SApple OSS Distributions 	case kIONVRAMOperationReset:
949e6231be0SApple OSS Distributions 		opCountKey = kIODTNVRAMDiagsDeleteKey;
950e6231be0SApple OSS Distributions 		existingEntry->setObject(kIODTNVRAMDiagsPresentKey, kOSBooleanFalse);
951e6231be0SApple OSS Distributions 		break;
952e6231be0SApple OSS Distributions 	case kIONVRAMOperationInit:
953e6231be0SApple OSS Distributions 		varSize = OSNumber::withNumber((size_t)data, 64);
954e6231be0SApple OSS Distributions 		existingEntry->setObject(kIODTNVRAMDiagsInitKey, varSize);
955e6231be0SApple OSS Distributions 		existingEntry->setObject(kIODTNVRAMDiagsSizeKey, varSize);
956e6231be0SApple OSS Distributions 		existingEntry->setObject(kIODTNVRAMDiagsPresentKey, kOSBooleanTrue);
957e6231be0SApple OSS Distributions 		break;
958e6231be0SApple OSS Distributions 	default:
959aca3beaaSApple OSS Distributions 		goto unlock;
960e6231be0SApple OSS Distributions 	}
961e6231be0SApple OSS Distributions 
962e6231be0SApple OSS Distributions 	if (opCountKey) {
963e6231be0SApple OSS Distributions 		currentCount.reset(OSDynamicCast(OSNumber, existingEntry->getObject(opCountKey)), OSRetain);
964e6231be0SApple OSS Distributions 
965e6231be0SApple OSS Distributions 		if (currentCount == nullptr) {
966e6231be0SApple OSS Distributions 			currentCount = OSNumber::withNumber(1, 64);
967e6231be0SApple OSS Distributions 		} else {
968e6231be0SApple OSS Distributions 			currentCount->addValue(1);
969e6231be0SApple OSS Distributions 		}
970e6231be0SApple OSS Distributions 
971e6231be0SApple OSS Distributions 		existingEntry->setObject(opCountKey, currentCount);
972e6231be0SApple OSS Distributions 	}
973e6231be0SApple OSS Distributions 
974e6231be0SApple OSS Distributions 	_stats->setObject(entryKey, existingEntry);
975aca3beaaSApple OSS Distributions 
976aca3beaaSApple OSS Distributions unlock:
977e6231be0SApple OSS Distributions 	NVRAMUNLOCK();
978e6231be0SApple OSS Distributions 
979e6231be0SApple OSS Distributions exit:
980e6231be0SApple OSS Distributions 	IODeleteData(entryKey, char, entryKeySize);
981e6231be0SApple OSS Distributions 
982e6231be0SApple OSS Distributions 	return;
983e6231be0SApple OSS Distributions }
984e6231be0SApple OSS Distributions 
985e6231be0SApple OSS Distributions bool
serializeStats(void *,OSSerialize * serializer)986e6231be0SApple OSS Distributions IODTNVRAMDiags::serializeStats(void *, OSSerialize * serializer)
987e6231be0SApple OSS Distributions {
988e6231be0SApple OSS Distributions 	bool ok;
989e6231be0SApple OSS Distributions 
990e6231be0SApple OSS Distributions 	NVRAMREADLOCK();
991e6231be0SApple OSS Distributions 	ok = _stats->serialize(serializer);
992e6231be0SApple OSS Distributions 	NVRAMUNLOCK();
993e6231be0SApple OSS Distributions 
994e6231be0SApple OSS Distributions 	return ok;
995e6231be0SApple OSS Distributions }
996e6231be0SApple OSS Distributions 
997e6231be0SApple OSS Distributions // ************************** IODTNVRAMVariables ****************************
998e6231be0SApple OSS Distributions 
999bb611c8fSApple OSS Distributions // private IOService based class for publishing distinct dictionary properties on
1000bb611c8fSApple OSS Distributions // for easy ioreg access since the serializeProperties call is overloaded and is used
1001bb611c8fSApple OSS Distributions // as variable access
1002bb611c8fSApple OSS Distributions class IODTNVRAMVariables : public IOService
1003bb611c8fSApple OSS Distributions {
1004bb611c8fSApple OSS Distributions 	OSDeclareDefaultStructors(IODTNVRAMVariables)
1005bb611c8fSApple OSS Distributions private:
1006bb611c8fSApple OSS Distributions 	IODTNVRAM        *_provider;
1007bb611c8fSApple OSS Distributions 	uuid_t           _guid;
1008aca3beaaSApple OSS Distributions 	bool             _systemActive;
1009bb611c8fSApple OSS Distributions 
1010bb611c8fSApple OSS Distributions public:
1011aca3beaaSApple OSS Distributions 	bool                    init(const uuid_t guid, const bool systemActive);
1012bb611c8fSApple OSS Distributions 	virtual bool            start(IOService * provider) APPLE_KEXT_OVERRIDE;
1013e6231be0SApple OSS Distributions 
1014bb611c8fSApple OSS Distributions 	virtual bool            serializeProperties(OSSerialize *s) const APPLE_KEXT_OVERRIDE;
1015e6231be0SApple OSS Distributions 	virtual OSPtr<OSObject> copyProperty(const OSSymbol *aKey) const APPLE_KEXT_OVERRIDE;
1016e6231be0SApple OSS Distributions 	virtual OSObject        *getProperty(const OSSymbol *aKey) const APPLE_KEXT_OVERRIDE;
1017e6231be0SApple OSS Distributions 	virtual bool            setProperty(const OSSymbol *aKey, OSObject *anObject) APPLE_KEXT_OVERRIDE;
1018e6231be0SApple OSS Distributions 	virtual IOReturn        setProperties(OSObject *properties) APPLE_KEXT_OVERRIDE;
1019e6231be0SApple OSS Distributions 	virtual void            removeProperty(const OSSymbol *aKey) APPLE_KEXT_OVERRIDE;
1020bb611c8fSApple OSS Distributions };
1021bb611c8fSApple OSS Distributions 
OSDefineMetaClassAndStructors(IODTNVRAMVariables,IOService)1022bb611c8fSApple OSS Distributions OSDefineMetaClassAndStructors(IODTNVRAMVariables, IOService)
1023bb611c8fSApple OSS Distributions 
1024bb611c8fSApple OSS Distributions bool
1025aca3beaaSApple OSS Distributions IODTNVRAMVariables::init(const uuid_t guid, const bool systemActive)
1026bb611c8fSApple OSS Distributions {
10275c2921b0SApple OSS Distributions 	require(super::init(), fail);
1028bb611c8fSApple OSS Distributions 
10295c2921b0SApple OSS Distributions 	uuid_copy(_guid, guid);
1030aca3beaaSApple OSS Distributions 	_systemActive = systemActive;
1031bb611c8fSApple OSS Distributions 
1032bb611c8fSApple OSS Distributions 	return true;
1033bb611c8fSApple OSS Distributions 
1034e6231be0SApple OSS Distributions fail:
1035bb611c8fSApple OSS Distributions 	return false;
1036bb611c8fSApple OSS Distributions }
1037bb611c8fSApple OSS Distributions 
1038bb611c8fSApple OSS Distributions bool
start(IOService * provider)1039bb611c8fSApple OSS Distributions IODTNVRAMVariables::start(IOService * provider)
1040bb611c8fSApple OSS Distributions {
1041aca3beaaSApple OSS Distributions 	_provider = OSDynamicCast(IODTNVRAM, provider);
1042aca3beaaSApple OSS Distributions 	if (_provider == nullptr) {
1043e6231be0SApple OSS Distributions 		goto error;
1044e6231be0SApple OSS Distributions 	}
1045bb611c8fSApple OSS Distributions 
1046aca3beaaSApple OSS Distributions 	if (!super::start(provider)) {
1047e6231be0SApple OSS Distributions 		goto error;
1048e6231be0SApple OSS Distributions 	}
1049bb611c8fSApple OSS Distributions 
1050bb611c8fSApple OSS Distributions 	registerService();
1051bb611c8fSApple OSS Distributions 
1052bb611c8fSApple OSS Distributions 	return true;
1053bb611c8fSApple OSS Distributions 
1054bb611c8fSApple OSS Distributions error:
1055bb611c8fSApple OSS Distributions 	stop(provider);
1056bb611c8fSApple OSS Distributions 
1057bb611c8fSApple OSS Distributions 	return false;
1058bb611c8fSApple OSS Distributions }
1059bb611c8fSApple OSS Distributions 
1060bb611c8fSApple OSS Distributions bool
serializeProperties(OSSerialize * s) const1061bb611c8fSApple OSS Distributions IODTNVRAMVariables::serializeProperties(OSSerialize *s) const
1062bb611c8fSApple OSS Distributions {
1063bb611c8fSApple OSS Distributions 	const OSSymbol                    *key;
1064bb611c8fSApple OSS Distributions 	OSSharedPtr<OSDictionary>         dict;
1065bb611c8fSApple OSS Distributions 	OSSharedPtr<OSCollectionIterator> iter;
1066aca3beaaSApple OSS Distributions 	OSSharedPtr<OSDictionary>         localVariables = _provider->_varDict;
1067e6231be0SApple OSS Distributions 	bool                              ok = false;
1068bb611c8fSApple OSS Distributions 
1069e6231be0SApple OSS Distributions 	dict = OSDictionary::withCapacity(localVariables->getCount());
1070e6231be0SApple OSS Distributions 	if (dict == nullptr) {
1071e6231be0SApple OSS Distributions 		DEBUG_ERROR("No dictionary\n");
1072e6231be0SApple OSS Distributions 		goto exit;
1073e6231be0SApple OSS Distributions 	}
1074bb611c8fSApple OSS Distributions 
1075e6231be0SApple OSS Distributions 	iter = OSCollectionIterator::withCollection(localVariables.get());
1076e6231be0SApple OSS Distributions 	if (iter == nullptr) {
1077e6231be0SApple OSS Distributions 		DEBUG_ERROR("failed to create iterator\n");
1078e6231be0SApple OSS Distributions 		goto exit;
1079e6231be0SApple OSS Distributions 	}
1080bb611c8fSApple OSS Distributions 
1081bb611c8fSApple OSS Distributions 	while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
1082aca3beaaSApple OSS Distributions 		if (verifyPermission(kIONVRAMOperationRead, key, _systemActive)) {
1083aca3beaaSApple OSS Distributions 			uuid_t guid;
1084aca3beaaSApple OSS Distributions 			const char *name;
1085aca3beaaSApple OSS Distributions 
1086aca3beaaSApple OSS Distributions 			parseVariableName(key, &guid, &name);
1087aca3beaaSApple OSS Distributions 
1088aca3beaaSApple OSS Distributions 			if (uuid_compare(_guid, guid) == 0) {
1089aca3beaaSApple OSS Distributions 				OSSharedPtr<const OSSymbol> sym = OSSymbol::withCString(name);
1090aca3beaaSApple OSS Distributions 				dict->setObject(sym.get(), localVariables->getObject(key));
1091aca3beaaSApple OSS Distributions 			}
1092bb611c8fSApple OSS Distributions 		}
1093bb611c8fSApple OSS Distributions 	}
1094bb611c8fSApple OSS Distributions 
1095e6231be0SApple OSS Distributions 	ok = dict->serialize(s);
1096bb611c8fSApple OSS Distributions 
1097bb611c8fSApple OSS Distributions exit:
1098e6231be0SApple OSS Distributions 	DEBUG_INFO("ok=%d\n", ok);
1099e6231be0SApple OSS Distributions 	return ok;
1100bb611c8fSApple OSS Distributions }
1101bb611c8fSApple OSS Distributions 
1102e6231be0SApple OSS Distributions OSPtr<OSObject>
copyProperty(const OSSymbol * aKey) const1103e6231be0SApple OSS Distributions IODTNVRAMVariables::copyProperty(const OSSymbol *aKey) const
1104e6231be0SApple OSS Distributions {
1105e6231be0SApple OSS Distributions 	if (_provider && !skipKey(aKey)) {
1106e6231be0SApple OSS Distributions 		DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
1107e6231be0SApple OSS Distributions 
11085c2921b0SApple OSS Distributions 		return _provider->copyPropertyWithGUIDAndName(_guid, aKey->getCStringNoCopy());
1109e6231be0SApple OSS Distributions 	} else {
1110e6231be0SApple OSS Distributions 		return nullptr;
1111e6231be0SApple OSS Distributions 	}
1112e6231be0SApple OSS Distributions }
1113e6231be0SApple OSS Distributions 
1114e6231be0SApple OSS Distributions OSObject *
getProperty(const OSSymbol * aKey) const1115e6231be0SApple OSS Distributions IODTNVRAMVariables::getProperty(const OSSymbol *aKey) const
1116e6231be0SApple OSS Distributions {
1117e6231be0SApple OSS Distributions 	OSSharedPtr<OSObject> theObject = copyProperty(aKey);
1118e6231be0SApple OSS Distributions 
1119e6231be0SApple OSS Distributions 	return theObject.get();
1120e6231be0SApple OSS Distributions }
1121e6231be0SApple OSS Distributions 
1122e6231be0SApple OSS Distributions bool
setProperty(const OSSymbol * aKey,OSObject * anObject)1123e6231be0SApple OSS Distributions IODTNVRAMVariables::setProperty(const OSSymbol *aKey, OSObject *anObject)
1124e6231be0SApple OSS Distributions {
1125e6231be0SApple OSS Distributions 	if (_provider) {
11265c2921b0SApple OSS Distributions 		return _provider->setPropertyWithGUIDAndName(_guid, aKey->getCStringNoCopy(), anObject) == kIOReturnSuccess;
1127e6231be0SApple OSS Distributions 	} else {
1128e6231be0SApple OSS Distributions 		return false;
1129e6231be0SApple OSS Distributions 	}
1130e6231be0SApple OSS Distributions }
1131e6231be0SApple OSS Distributions 
1132e6231be0SApple OSS Distributions IOReturn
setProperties(OSObject * properties)1133e6231be0SApple OSS Distributions IODTNVRAMVariables::setProperties(OSObject *properties)
1134e6231be0SApple OSS Distributions {
1135e6231be0SApple OSS Distributions 	IOReturn                          ret = kIOReturnSuccess;
1136e6231be0SApple OSS Distributions 	OSObject                          *object;
1137e6231be0SApple OSS Distributions 	const OSSymbol                    *key;
1138e6231be0SApple OSS Distributions 	OSDictionary                      *dict;
1139e6231be0SApple OSS Distributions 	OSSharedPtr<OSCollectionIterator> iter;
1140e6231be0SApple OSS Distributions 
1141e6231be0SApple OSS Distributions 	dict = OSDynamicCast(OSDictionary, properties);
1142e6231be0SApple OSS Distributions 	if (dict == nullptr) {
1143e6231be0SApple OSS Distributions 		DEBUG_ERROR("Not a dictionary\n");
1144e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
1145e6231be0SApple OSS Distributions 	}
1146e6231be0SApple OSS Distributions 
1147e6231be0SApple OSS Distributions 	iter = OSCollectionIterator::withCollection(dict);
1148e6231be0SApple OSS Distributions 	if (iter == nullptr) {
1149e6231be0SApple OSS Distributions 		DEBUG_ERROR("Couldn't create iterator\n");
1150e6231be0SApple OSS Distributions 		return kIOReturnBadArgument;
1151e6231be0SApple OSS Distributions 	}
1152e6231be0SApple OSS Distributions 
1153e6231be0SApple OSS Distributions 	while (ret == kIOReturnSuccess) {
1154e6231be0SApple OSS Distributions 		key = OSDynamicCast(OSSymbol, iter->getNextObject());
1155e6231be0SApple OSS Distributions 		if (key == nullptr) {
1156e6231be0SApple OSS Distributions 			break;
1157e6231be0SApple OSS Distributions 		}
1158e6231be0SApple OSS Distributions 
1159e6231be0SApple OSS Distributions 		object = dict->getObject(key);
1160e6231be0SApple OSS Distributions 		if (object == nullptr) {
1161e6231be0SApple OSS Distributions 			continue;
1162e6231be0SApple OSS Distributions 		}
1163e6231be0SApple OSS Distributions 
11645c2921b0SApple OSS Distributions 		ret = _provider->setPropertyWithGUIDAndName(_guid, key->getCStringNoCopy(), object);
1165e6231be0SApple OSS Distributions 	}
1166e6231be0SApple OSS Distributions 
1167e6231be0SApple OSS Distributions 	DEBUG_INFO("ret=%#08x\n", ret);
1168e6231be0SApple OSS Distributions 
1169e6231be0SApple OSS Distributions 	return ret;
1170e6231be0SApple OSS Distributions }
1171e6231be0SApple OSS Distributions 
1172e6231be0SApple OSS Distributions void
removeProperty(const OSSymbol * aKey)1173e6231be0SApple OSS Distributions IODTNVRAMVariables::removeProperty(const OSSymbol *aKey)
1174e6231be0SApple OSS Distributions {
11755c2921b0SApple OSS Distributions 	_provider->removePropertyWithGUIDAndName(_guid, aKey->getCStringNoCopy());
1176e6231be0SApple OSS Distributions }
1177e6231be0SApple OSS Distributions 
1178e7776783SApple OSS Distributions // ************************** Format Handlers ***************************
11795c2921b0SApple OSS Distributions class IODTNVRAMFormatHandler
11805c2921b0SApple OSS Distributions {
11815c2921b0SApple OSS Distributions protected:
11825c2921b0SApple OSS Distributions 	uint32_t _bankSize;
11835c2921b0SApple OSS Distributions 	uint32_t _bankCount;
11845c2921b0SApple OSS Distributions 	uint32_t _currentBank;
11855c2921b0SApple OSS Distributions 
11865c2921b0SApple OSS Distributions public:
11875c2921b0SApple OSS Distributions 	virtual
11885c2921b0SApple OSS Distributions 	~IODTNVRAMFormatHandler();
11895c2921b0SApple OSS Distributions 	virtual bool     getNVRAMProperties(void);
1190aca3beaaSApple OSS Distributions 	virtual IOReturn unserializeVariables(void) = 0;
11915c2921b0SApple OSS Distributions 	virtual IOReturn setVariable(const uuid_t varGuid, const char *variableName, OSObject *object) = 0;
11925c2921b0SApple OSS Distributions 	virtual bool     setController(IONVRAMController *_nvramController) = 0;
119394d3b452SApple OSS Distributions 	virtual IOReturn sync(void) = 0;
11945c2921b0SApple OSS Distributions 	virtual IOReturn flush(const uuid_t guid, IONVRAMOperation op) = 0;
11955c2921b0SApple OSS Distributions 	virtual void     reload(void) = 0;
11965c2921b0SApple OSS Distributions 	virtual uint32_t getGeneration(void) const = 0;
11975c2921b0SApple OSS Distributions 	virtual uint32_t getVersion(void) const = 0;
11985c2921b0SApple OSS Distributions 	virtual uint32_t getSystemUsed(void) const = 0;
11995c2921b0SApple OSS Distributions 	virtual uint32_t getCommonUsed(void) const = 0;
1200aca3beaaSApple OSS Distributions 	virtual bool     getSystemPartitionActive(void) const = 0;
12015c2921b0SApple OSS Distributions };
1202e7776783SApple OSS Distributions 
~IODTNVRAMFormatHandler()1203e7776783SApple OSS Distributions IODTNVRAMFormatHandler::~IODTNVRAMFormatHandler()
1204e7776783SApple OSS Distributions {
1205e7776783SApple OSS Distributions }
1206e7776783SApple OSS Distributions 
12075c2921b0SApple OSS Distributions bool
getNVRAMProperties()12085c2921b0SApple OSS Distributions IODTNVRAMFormatHandler::getNVRAMProperties()
12095c2921b0SApple OSS Distributions {
12105c2921b0SApple OSS Distributions 	bool                         ok    = false;
12115c2921b0SApple OSS Distributions 	OSSharedPtr<IORegistryEntry> entry;
12125c2921b0SApple OSS Distributions 	OSSharedPtr<OSObject>        prop;
12135c2921b0SApple OSS Distributions 	OSData *                     data;
12145c2921b0SApple OSS Distributions 
12155c2921b0SApple OSS Distributions 	entry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
12165c2921b0SApple OSS Distributions 	require_action(entry, exit, DEBUG_ERROR("Unable to find chosen node\n"));
12175c2921b0SApple OSS Distributions 
12185c2921b0SApple OSS Distributions 	prop = entry->copyProperty(kNVRAMBankSizeKey);
12195c2921b0SApple OSS Distributions 	require_action(prop, exit, DEBUG_ERROR("Unable to find %s property\n", kNVRAMBankSizeKey));
12205c2921b0SApple OSS Distributions 
12215c2921b0SApple OSS Distributions 	data = OSDynamicCast(OSData, prop.get());
12225c2921b0SApple OSS Distributions 	require(data, exit);
12235c2921b0SApple OSS Distributions 
12245c2921b0SApple OSS Distributions 	_bankSize = *((uint32_t *)data->getBytesNoCopy());
12255c2921b0SApple OSS Distributions 
12265c2921b0SApple OSS Distributions 	prop = entry->copyProperty(kNVRAMBankCountKey);
12275c2921b0SApple OSS Distributions 	require_action(prop, exit, DEBUG_ERROR("Unable to find %s property\n", kNVRAMBankCountKey));
12285c2921b0SApple OSS Distributions 
12295c2921b0SApple OSS Distributions 	data = OSDynamicCast(OSData, prop.get());
12305c2921b0SApple OSS Distributions 	require(data, exit);
12315c2921b0SApple OSS Distributions 
12325c2921b0SApple OSS Distributions 	_bankCount = *((uint32_t *)data->getBytesNoCopy());
12335c2921b0SApple OSS Distributions 
12345c2921b0SApple OSS Distributions 	prop = entry->copyProperty(kNVRAMCurrentBankKey);
12355c2921b0SApple OSS Distributions 	require_action(prop, exit, DEBUG_ERROR("Unable to find %s property\n", kNVRAMCurrentBankKey));
12365c2921b0SApple OSS Distributions 
12375c2921b0SApple OSS Distributions 	data = OSDynamicCast(OSData, prop.get());
12385c2921b0SApple OSS Distributions 	require(data, exit);
12395c2921b0SApple OSS Distributions 
12405c2921b0SApple OSS Distributions 	_currentBank = *((uint32_t *)data->getBytesNoCopy());
12415c2921b0SApple OSS Distributions 
12425c2921b0SApple OSS Distributions 	ok = true;
12435c2921b0SApple OSS Distributions 
12445c2921b0SApple OSS Distributions 	DEBUG_ALWAYS("_bankSize=%#X, _bankCount=%#X, _currentBank=%#X\n", _bankSize, _bankCount, _currentBank);
12455c2921b0SApple OSS Distributions 
12465c2921b0SApple OSS Distributions exit:
12475c2921b0SApple OSS Distributions 	return ok;
12485c2921b0SApple OSS Distributions }
12495c2921b0SApple OSS Distributions 
1250e7776783SApple OSS Distributions #include "IONVRAMCHRPHandler.cpp"
1251e7776783SApple OSS Distributions 
1252e7776783SApple OSS Distributions #include "IONVRAMV3Handler.cpp"
1253e6231be0SApple OSS Distributions 
1254e6231be0SApple OSS Distributions // **************************** IODTNVRAM *********************************
1255e6231be0SApple OSS Distributions 
1256a5e72196SApple OSS Distributions bool
init(IORegistryEntry * old,const IORegistryPlane * plane)1257a5e72196SApple OSS Distributions IODTNVRAM::init(IORegistryEntry *old, const IORegistryPlane *plane)
1258c1dac77fSApple OSS Distributions {
1259bb611c8fSApple OSS Distributions 	OSSharedPtr<OSDictionary> dict;
1260c1dac77fSApple OSS Distributions 
1261e7776783SApple OSS Distributions 	DEBUG_INFO("...\n");
1262e7776783SApple OSS Distributions 
1263e6231be0SApple OSS Distributions 	require(super::init(old, plane), fail);
1264c1dac77fSApple OSS Distributions 
1265*8d741a5dSApple OSS Distributions #if CONFIG_CSR && XNU_TARGET_OS_OSX
1266e6231be0SApple OSS Distributions 	gInternalBuild = (csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0);
1267*8d741a5dSApple OSS Distributions #elif defined(DEBUG) || defined(DEVELOPMENT)
1268*8d741a5dSApple OSS Distributions 	gInternalBuild = true;
1269*8d741a5dSApple OSS Distributions #endif
1270e6231be0SApple OSS Distributions 	DEBUG_INFO("gInternalBuild = %d\n", gInternalBuild);
1271c1dac77fSApple OSS Distributions 
1272e6231be0SApple OSS Distributions 	_variableLock = IORWLockAlloc();
1273e6231be0SApple OSS Distributions 	require(_variableLock != nullptr, fail);
1274e6231be0SApple OSS Distributions 
1275e6231be0SApple OSS Distributions 	_controllerLock = IOLockAlloc();
1276e6231be0SApple OSS Distributions 	require(_controllerLock != nullptr, fail);
1277bb611c8fSApple OSS Distributions 
1278e7776783SApple OSS Distributions 	// Clear the IORegistryEntry property table
1279bb611c8fSApple OSS Distributions 	dict =  OSDictionary::withCapacity(1);
1280e6231be0SApple OSS Distributions 	require(dict != nullptr, fail);
1281e6231be0SApple OSS Distributions 
1282bb611c8fSApple OSS Distributions 	setPropertyTable(dict.get());
1283bb611c8fSApple OSS Distributions 	dict.reset();
1284bb611c8fSApple OSS Distributions 
1285e6231be0SApple OSS Distributions 	return true;
1286e6231be0SApple OSS Distributions 
1287e6231be0SApple OSS Distributions fail:
1288a5e72196SApple OSS Distributions 	return false;
1289a5e72196SApple OSS Distributions }
1290fad439e7SApple OSS Distributions 
1291e6231be0SApple OSS Distributions bool
start(IOService * provider)1292e6231be0SApple OSS Distributions IODTNVRAM::start(IOService *provider)
1293e6231be0SApple OSS Distributions {
1294e6231be0SApple OSS Distributions 	OSSharedPtr<OSNumber> version;
1295e6231be0SApple OSS Distributions 
1296e7776783SApple OSS Distributions 	DEBUG_INFO("...\n");
1297e7776783SApple OSS Distributions 
1298e6231be0SApple OSS Distributions 	require(super::start(provider), fail);
1299e6231be0SApple OSS Distributions 
1300e7776783SApple OSS Distributions 	// Check if our overridden init function was called
1301e6231be0SApple OSS Distributions 	// If not, skip any additional initialization being done here.
1302e6231be0SApple OSS Distributions 	// This is not an error we just need to successfully exit this function to allow
1303e6231be0SApple OSS Distributions 	// AppleEFIRuntime to proceed and take over operation
1304e7776783SApple OSS Distributions 	require_action(_controllerLock != nullptr, no_common, DEBUG_INFO("x86 init\n"));
1305e6231be0SApple OSS Distributions 
1306e6231be0SApple OSS Distributions 	_diags = new IODTNVRAMDiags;
1307e6231be0SApple OSS Distributions 	if (!_diags || !_diags->init()) {
1308e6231be0SApple OSS Distributions 		DEBUG_ERROR("Unable to create/init the diags service\n");
1309e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(_diags);
1310e6231be0SApple OSS Distributions 		goto fail;
1311e6231be0SApple OSS Distributions 	}
1312e6231be0SApple OSS Distributions 
1313e6231be0SApple OSS Distributions 	if (!_diags->attach(this)) {
1314e6231be0SApple OSS Distributions 		DEBUG_ERROR("Unable to attach the diags service!\n");
1315e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(_diags);
1316e6231be0SApple OSS Distributions 		goto fail;
1317e6231be0SApple OSS Distributions 	}
1318e6231be0SApple OSS Distributions 
1319e7776783SApple OSS Distributions 	if (!_diags->start(this)) {
1320e6231be0SApple OSS Distributions 		DEBUG_ERROR("Unable to start the diags service!\n");
1321e6231be0SApple OSS Distributions 		_diags->detach(this);
1322e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(_diags);
1323e6231be0SApple OSS Distributions 		goto fail;
1324a5e72196SApple OSS Distributions 	}
1325c1dac77fSApple OSS Distributions 
13265c2921b0SApple OSS Distributions 	_notifier = new IODTNVRAMPlatformNotifier;
13275c2921b0SApple OSS Distributions 	if (!_notifier || !_notifier->init()) {
13285c2921b0SApple OSS Distributions 		DEBUG_ERROR("Unable to create/init the notifier service\n");
13295c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(_notifier);
13305c2921b0SApple OSS Distributions 		goto fail;
13315c2921b0SApple OSS Distributions 	}
13325c2921b0SApple OSS Distributions 
13335c2921b0SApple OSS Distributions 	if (!_notifier->attach(this)) {
13345c2921b0SApple OSS Distributions 		DEBUG_ERROR("Unable to attach the notifier service!\n");
13355c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(_notifier);
13365c2921b0SApple OSS Distributions 		goto fail;
13375c2921b0SApple OSS Distributions 	}
13385c2921b0SApple OSS Distributions 
13395c2921b0SApple OSS Distributions 	if (!_notifier->start(this)) {
13405c2921b0SApple OSS Distributions 		DEBUG_ERROR("Unable to start the notifier service!\n");
13415c2921b0SApple OSS Distributions 		_notifier->detach(this);
13425c2921b0SApple OSS Distributions 		OSSafeReleaseNULL(_notifier);
13435c2921b0SApple OSS Distributions 		goto fail;
13445c2921b0SApple OSS Distributions 	}
13455c2921b0SApple OSS Distributions 
1346e7776783SApple OSS Distributions 	// This will load the proxied variable data which will call back into
1347e7776783SApple OSS Distributions 	// IODTNVRAM for the variable sets which will also update the system/common services
1348e7776783SApple OSS Distributions 	initImageFormat();
1349186b8fceSApple OSS Distributions 
1350e7776783SApple OSS Distributions 	version = OSNumber::withNumber(_format->getVersion(), 32);
1351e6231be0SApple OSS Distributions 	_diags->setProperty(kCurrentNVRAMVersionKey, version.get());
1352e6231be0SApple OSS Distributions 
1353e7776783SApple OSS Distributions 	if (_format->getSystemUsed()) {
1354bb611c8fSApple OSS Distributions 		_systemService = new IODTNVRAMVariables;
1355bb611c8fSApple OSS Distributions 
1356aca3beaaSApple OSS Distributions 		if (!_systemService || !_systemService->init(gAppleSystemVariableGuid, _format->getSystemPartitionActive())) {
1357bb611c8fSApple OSS Distributions 			DEBUG_ERROR("Unable to start the system service!\n");
1358e6231be0SApple OSS Distributions 			OSSafeReleaseNULL(_systemService);
1359bb611c8fSApple OSS Distributions 			goto no_system;
1360bb611c8fSApple OSS Distributions 		}
1361bb611c8fSApple OSS Distributions 
1362bb611c8fSApple OSS Distributions 		_systemService->setName("options-system");
1363bb611c8fSApple OSS Distributions 
1364bb611c8fSApple OSS Distributions 		if (!_systemService->attach(this)) {
1365bb611c8fSApple OSS Distributions 			DEBUG_ERROR("Unable to attach the system service!\n");
1366bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(_systemService);
1367bb611c8fSApple OSS Distributions 			goto no_system;
1368bb611c8fSApple OSS Distributions 		}
1369bb611c8fSApple OSS Distributions 
1370bb611c8fSApple OSS Distributions 		if (!_systemService->start(this)) {
1371bb611c8fSApple OSS Distributions 			DEBUG_ERROR("Unable to start the system service!\n");
1372bb611c8fSApple OSS Distributions 			_systemService->detach(this);
1373bb611c8fSApple OSS Distributions 			OSSafeReleaseNULL(_systemService);
1374bb611c8fSApple OSS Distributions 			goto no_system;
1375bb611c8fSApple OSS Distributions 		}
1376bb611c8fSApple OSS Distributions 	}
1377bb611c8fSApple OSS Distributions 
1378bb611c8fSApple OSS Distributions no_system:
1379bb611c8fSApple OSS Distributions 	_commonService = new IODTNVRAMVariables;
1380bb611c8fSApple OSS Distributions 
1381aca3beaaSApple OSS Distributions 	if (!_commonService || !_commonService->init(gAppleNVRAMGuid, _format->getSystemPartitionActive())) {
1382bb611c8fSApple OSS Distributions 		DEBUG_ERROR("Unable to start the common service!\n");
1383e6231be0SApple OSS Distributions 		OSSafeReleaseNULL(_commonService);
1384bb611c8fSApple OSS Distributions 		goto no_common;
1385bb611c8fSApple OSS Distributions 	}
1386bb611c8fSApple OSS Distributions 
1387bb611c8fSApple OSS Distributions 	_commonService->setName("options-common");
1388bb611c8fSApple OSS Distributions 
1389bb611c8fSApple OSS Distributions 	if (!_commonService->attach(this)) {
1390bb611c8fSApple OSS Distributions 		DEBUG_ERROR("Unable to attach the common service!\n");
1391bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(_commonService);
1392bb611c8fSApple OSS Distributions 		goto no_common;
1393bb611c8fSApple OSS Distributions 	}
1394bb611c8fSApple OSS Distributions 
1395bb611c8fSApple OSS Distributions 	if (!_commonService->start(this)) {
1396bb611c8fSApple OSS Distributions 		DEBUG_ERROR("Unable to start the common service!\n");
1397e6231be0SApple OSS Distributions 		_commonService->detach(this);
1398bb611c8fSApple OSS Distributions 		OSSafeReleaseNULL(_commonService);
1399bb611c8fSApple OSS Distributions 		goto no_common;
1400bb611c8fSApple OSS Distributions 	}
1401e6231be0SApple OSS Distributions 
1402bb611c8fSApple OSS Distributions no_common:
1403e6231be0SApple OSS Distributions 	return true;
1404e6231be0SApple OSS Distributions 
1405e6231be0SApple OSS Distributions fail:
1406e6231be0SApple OSS Distributions 	stop(provider);
1407e6231be0SApple OSS Distributions 	return false;
1408e6231be0SApple OSS Distributions }
1409e6231be0SApple OSS Distributions 
1410e6231be0SApple OSS Distributions void
initImageFormat(void)1411e7776783SApple OSS Distributions IODTNVRAM::initImageFormat(void)
1412e6231be0SApple OSS Distributions {
1413e6231be0SApple OSS Distributions 	OSSharedPtr<IORegistryEntry> entry;
1414e7776783SApple OSS Distributions 	OSSharedPtr<OSObject>        prop;
1415e7776783SApple OSS Distributions 	const char                   *proxyDataKey = "nvram-proxy-data";
1416e7776783SApple OSS Distributions 	const char                   *bankSizeKey = "nvram-bank-size";
1417aca3beaaSApple OSS Distributions 	OSData                       *data = nullptr;
1418e7776783SApple OSS Distributions 	uint32_t                     size = 0;
1419aca3beaaSApple OSS Distributions 	const uint8_t                *image = nullptr;
1420e6231be0SApple OSS Distributions 
1421e6231be0SApple OSS Distributions 	entry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
1422e7776783SApple OSS Distributions 
1423e7776783SApple OSS Distributions 	require(entry != nullptr, skip);
1424e7776783SApple OSS Distributions 
1425e7776783SApple OSS Distributions 	prop = entry->copyProperty(bankSizeKey);
1426e7776783SApple OSS Distributions 	require(prop != nullptr, skip);
1427e7776783SApple OSS Distributions 
1428e6231be0SApple OSS Distributions 	data = OSDynamicCast(OSData, prop.get());
1429e7776783SApple OSS Distributions 	require(data != nullptr, skip);
1430e7776783SApple OSS Distributions 
1431e7776783SApple OSS Distributions 	size = *((uint32_t*)data->getBytesNoCopy());
14321031c584SApple OSS Distributions 	require_action(size != 0, skip, panic("NVRAM size is 0 bytes, possibly due to bad config with iBoot + xnu mismatch"));
1433e7776783SApple OSS Distributions 	DEBUG_ALWAYS("NVRAM size is %u bytes\n", size);
1434e7776783SApple OSS Distributions 
1435e7776783SApple OSS Distributions 	prop = entry->copyProperty(proxyDataKey);
1436e7776783SApple OSS Distributions 	require(prop != nullptr, skip);
1437e7776783SApple OSS Distributions 
1438e7776783SApple OSS Distributions 	data = OSDynamicCast(OSData, prop.get());
1439aca3beaaSApple OSS Distributions 	require_action(data != nullptr, skip, DEBUG_ERROR("No proxy data!\n"));
1440e7776783SApple OSS Distributions 
1441aca3beaaSApple OSS Distributions 	image = (const uint8_t *)data->getBytesNoCopy();
1442aca3beaaSApple OSS Distributions 
1443aca3beaaSApple OSS Distributions skip:
1444aca3beaaSApple OSS Distributions 	if (IONVRAMV3Handler::isValidImage(image, size)) {
1445aca3beaaSApple OSS Distributions 		_format = IONVRAMV3Handler::init(this, image, size, _varDict);
1446e7776783SApple OSS Distributions 		require_action(_format, skip, panic("IONVRAMV3Handler creation failed\n"));
1447e7776783SApple OSS Distributions 	} else {
1448aca3beaaSApple OSS Distributions 		_format = IONVRAMCHRPHandler::init(this, image, size, _varDict);
1449e7776783SApple OSS Distributions 		require_action(_format, skip, panic("IONVRAMCHRPHandler creation failed\n"));
1450e6231be0SApple OSS Distributions 	}
1451e7776783SApple OSS Distributions 
1452aca3beaaSApple OSS Distributions 	_format->unserializeVariables();
1453aca3beaaSApple OSS Distributions 
1454aca3beaaSApple OSS Distributions 	dumpDict(_varDict.get());
1455aca3beaaSApple OSS Distributions 
1456e6231be0SApple OSS Distributions #if defined(RELEASE)
1457e6231be0SApple OSS Distributions 	if (entry != nullptr) {
1458e7776783SApple OSS Distributions 		entry->removeProperty(proxyDataKey);
1459e6231be0SApple OSS Distributions 	}
1460e7776783SApple OSS Distributions #endif
1461e7776783SApple OSS Distributions 
1462e7776783SApple OSS Distributions 	_lastDeviceSync = 0;
1463e7776783SApple OSS Distributions 	_freshInterval = true;
1464e6231be0SApple OSS Distributions }
1465e6231be0SApple OSS Distributions 
1466e6231be0SApple OSS Distributions void
registerNVRAMController(IONVRAMController * controller)1467e7776783SApple OSS Distributions IODTNVRAM::registerNVRAMController(IONVRAMController *controller)
1468e6231be0SApple OSS Distributions {
1469e6231be0SApple OSS Distributions 	DEBUG_INFO("setting controller\n");
1470e6231be0SApple OSS Distributions 
1471e7776783SApple OSS Distributions 	NVRAMWRITELOCK();
1472e6231be0SApple OSS Distributions 	CONTROLLERLOCK();
1473e7776783SApple OSS Distributions 
1474e7776783SApple OSS Distributions 	_format->setController(controller);
1475e7776783SApple OSS Distributions 
1476e6231be0SApple OSS Distributions 	CONTROLLERUNLOCK();
1477e7776783SApple OSS Distributions 	NVRAMUNLOCK();
1478e6231be0SApple OSS Distributions 
1479e6231be0SApple OSS Distributions 	return;
1480e6231be0SApple OSS Distributions }
1481e6231be0SApple OSS Distributions 
1482e7776783SApple OSS Distributions bool
safeToSync(void)1483e7776783SApple OSS Distributions IODTNVRAM::safeToSync(void)
1484e6231be0SApple OSS Distributions {
1485e7776783SApple OSS Distributions 	AbsoluteTime delta;
1486e7776783SApple OSS Distributions 	UInt64       delta_ns;
1487e7776783SApple OSS Distributions 	SInt32       delta_secs;
1488e7776783SApple OSS Distributions 
1489e7776783SApple OSS Distributions 	// delta interval went by
1490e7776783SApple OSS Distributions 	clock_get_uptime(&delta);
1491e7776783SApple OSS Distributions 
1492e7776783SApple OSS Distributions 	// Figure it in seconds.
1493e7776783SApple OSS Distributions 	absolutetime_to_nanoseconds(delta, &delta_ns);
1494e7776783SApple OSS Distributions 	delta_secs = (SInt32)(delta_ns / NSEC_PER_SEC);
1495e7776783SApple OSS Distributions 
1496e7776783SApple OSS Distributions 	if ((delta_secs > (_lastDeviceSync + MIN_SYNC_NOW_INTERVAL)) || _freshInterval) {
1497e7776783SApple OSS Distributions 		_lastDeviceSync = delta_secs;
1498e7776783SApple OSS Distributions 		_freshInterval = false;
1499e7776783SApple OSS Distributions 		return true;
1500e6231be0SApple OSS Distributions 	}
1501e6231be0SApple OSS Distributions 
1502e7776783SApple OSS Distributions 	return false;
1503c1dac77fSApple OSS Distributions }
1504c1dac77fSApple OSS Distributions 
150594d3b452SApple OSS Distributions IOReturn
syncInternal(bool rateLimit)1506a5e72196SApple OSS Distributions IODTNVRAM::syncInternal(bool rateLimit)
1507c1dac77fSApple OSS Distributions {
150894d3b452SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
150994d3b452SApple OSS Distributions 
1510bb611c8fSApple OSS Distributions 	DEBUG_INFO("rateLimit=%d\n", rateLimit);
1511bb611c8fSApple OSS Distributions 
1512e7776783SApple OSS Distributions 	if (!SAFE_TO_LOCK()) {
1513e7776783SApple OSS Distributions 		DEBUG_INFO("cannot lock\n");
151494d3b452SApple OSS Distributions 		goto exit;
1515a5e72196SApple OSS Distributions 	}
1516186b8fceSApple OSS Distributions 
15170f3703acSApple OSS Distributions 	// Rate limit requests to sync. Drivers that need this rate limiting will
15180f3703acSApple OSS Distributions 	// shadow the data and only write to flash when they get a sync call
1519e6231be0SApple OSS Distributions 	if (rateLimit) {
1520e6231be0SApple OSS Distributions 		if (safeToSync() == false) {
1521e6231be0SApple OSS Distributions 			DEBUG_INFO("safeToSync()=false\n");
152294d3b452SApple OSS Distributions 			goto exit;
1523a5e72196SApple OSS Distributions 		}
1524e6231be0SApple OSS Distributions 	}
1525e6231be0SApple OSS Distributions 
1526e7776783SApple OSS Distributions 	DEBUG_INFO("Calling sync()\n");
15275c2921b0SApple OSS Distributions 	record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "sync", "triggered");
1528e7776783SApple OSS Distributions 
1529e7776783SApple OSS Distributions 	NVRAMREADLOCK();
1530e6231be0SApple OSS Distributions 	CONTROLLERLOCK();
1531e6231be0SApple OSS Distributions 
153294d3b452SApple OSS Distributions 	ret = _format->sync();
1533e6231be0SApple OSS Distributions 
1534e6231be0SApple OSS Distributions 	CONTROLLERUNLOCK();
1535e7776783SApple OSS Distributions 	NVRAMUNLOCK();
1536e7776783SApple OSS Distributions 
153794d3b452SApple OSS Distributions 	record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "sync", "completed with ret=%08x", ret);
153894d3b452SApple OSS Distributions 
1539e7776783SApple OSS Distributions 	if (_diags) {
1540e7776783SApple OSS Distributions 		OSSharedPtr<OSNumber> generation = OSNumber::withNumber(_format->getGeneration(), 32);
1541e7776783SApple OSS Distributions 		_diags->setProperty(kCurrentGenerationCountKey, generation.get());
1542e7776783SApple OSS Distributions 	}
154394d3b452SApple OSS Distributions 
154494d3b452SApple OSS Distributions exit:
154594d3b452SApple OSS Distributions 	return ret;
15460f3703acSApple OSS Distributions }
15470f3703acSApple OSS Distributions 
154894d3b452SApple OSS Distributions IOReturn
sync(void)1549a5e72196SApple OSS Distributions IODTNVRAM::sync(void)
15500f3703acSApple OSS Distributions {
155194d3b452SApple OSS Distributions 	return syncInternal(false);
1552c1dac77fSApple OSS Distributions }
1553c1dac77fSApple OSS Distributions 
15545c2921b0SApple OSS Distributions void
reload(void)15555c2921b0SApple OSS Distributions IODTNVRAM::reload(void)
15565c2921b0SApple OSS Distributions {
15575c2921b0SApple OSS Distributions 	_format->reload();
15585c2921b0SApple OSS Distributions }
15595c2921b0SApple OSS Distributions 
1560*8d741a5dSApple OSS Distributions OSPtr<OSDictionary>
dictionaryWithProperties(void) const1561*8d741a5dSApple OSS Distributions IODTNVRAM::dictionaryWithProperties(void) const
1562c1dac77fSApple OSS Distributions {
1563aca3beaaSApple OSS Distributions 	const OSSymbol                    *canonicalKey;
1564aca3beaaSApple OSS Distributions 	OSSharedPtr<OSDictionary>         localVarDict, returnDict;
1565bb611c8fSApple OSS Distributions 	OSSharedPtr<OSCollectionIterator> iter;
1566bb611c8fSApple OSS Distributions 	unsigned int                      totalCapacity = 0;
1567aca3beaaSApple OSS Distributions 	uuid_t                            varGuid;
1568aca3beaaSApple OSS Distributions 	const char *                      varName;
1569c1dac77fSApple OSS Distributions 
1570e6231be0SApple OSS Distributions 	NVRAMREADLOCK();
1571aca3beaaSApple OSS Distributions 	if (_varDict) {
1572aca3beaaSApple OSS Distributions 		localVarDict = OSDictionary::withDictionary(_varDict.get());
1573a5e72196SApple OSS Distributions 	}
1574e6231be0SApple OSS Distributions 	NVRAMUNLOCK();
1575e6231be0SApple OSS Distributions 
1576aca3beaaSApple OSS Distributions 	if (localVarDict != nullptr) {
1577aca3beaaSApple OSS Distributions 		totalCapacity =  localVarDict->getCapacity();
1578aca3beaaSApple OSS Distributions 	}
1579c1dac77fSApple OSS Distributions 
1580aca3beaaSApple OSS Distributions 	returnDict = OSDictionary::withCapacity(totalCapacity);
1581bb611c8fSApple OSS Distributions 
1582aca3beaaSApple OSS Distributions 	if (returnDict == nullptr) {
1583bb611c8fSApple OSS Distributions 		DEBUG_ERROR("No dictionary\n");
1584e6231be0SApple OSS Distributions 		goto exit;
1585bb611c8fSApple OSS Distributions 	}
1586bb611c8fSApple OSS Distributions 
1587aca3beaaSApple OSS Distributions 	// Copy system entries first if present then copy unique other entries
1588aca3beaaSApple OSS Distributions 	iter = OSCollectionIterator::withCollection(localVarDict.get());
1589bb611c8fSApple OSS Distributions 	if (iter == nullptr) {
1590bb611c8fSApple OSS Distributions 		DEBUG_ERROR("failed to create iterator\n");
1591e6231be0SApple OSS Distributions 		goto exit;
1592bb611c8fSApple OSS Distributions 	}
1593bb611c8fSApple OSS Distributions 
1594aca3beaaSApple OSS Distributions 	while ((canonicalKey = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
1595aca3beaaSApple OSS Distributions 		parseVariableName(canonicalKey, &varGuid, &varName);
1596aca3beaaSApple OSS Distributions 
1597aca3beaaSApple OSS Distributions 		if ((uuid_compare(varGuid, gAppleSystemVariableGuid) == 0) &&
1598aca3beaaSApple OSS Distributions 		    verifyPermission(kIONVRAMOperationRead, varGuid, varName, _format->getSystemPartitionActive())) {
1599aca3beaaSApple OSS Distributions 			OSSharedPtr<const OSSymbol> returnKey = OSSymbol::withCString(varName);
1600aca3beaaSApple OSS Distributions 			returnDict->setObject(returnKey.get(), localVarDict->getObject(canonicalKey));
1601bb611c8fSApple OSS Distributions 		}
1602bb611c8fSApple OSS Distributions 	}
1603bb611c8fSApple OSS Distributions 
1604bb611c8fSApple OSS Distributions 	iter.reset();
1605bb611c8fSApple OSS Distributions 
1606aca3beaaSApple OSS Distributions 	iter = OSCollectionIterator::withCollection(localVarDict.get());
1607bb611c8fSApple OSS Distributions 	if (iter == nullptr) {
1608aca3beaaSApple OSS Distributions 		DEBUG_ERROR("failed to create iterator\n");
1609e6231be0SApple OSS Distributions 		goto exit;
1610bb611c8fSApple OSS Distributions 	}
1611bb611c8fSApple OSS Distributions 
1612aca3beaaSApple OSS Distributions 	while ((canonicalKey = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
1613aca3beaaSApple OSS Distributions 		parseVariableName(canonicalKey, &varGuid, &varName);
1614aca3beaaSApple OSS Distributions 
1615aca3beaaSApple OSS Distributions 		if (uuid_compare(varGuid, gAppleNVRAMGuid) == 0) {
1616aca3beaaSApple OSS Distributions 			if (returnDict->getObject(varName) != nullptr) {
1617bb611c8fSApple OSS Distributions 				// Skip non uniques
1618bb611c8fSApple OSS Distributions 				continue;
1619bb611c8fSApple OSS Distributions 			}
1620aca3beaaSApple OSS Distributions 
1621aca3beaaSApple OSS Distributions 			if (verifyPermission(kIONVRAMOperationRead, varGuid, varName, _format->getSystemPartitionActive())) {
1622aca3beaaSApple OSS Distributions 				OSSharedPtr<const OSSymbol> returnKey = OSSymbol::withCString(varName);
1623aca3beaaSApple OSS Distributions 				returnDict->setObject(returnKey.get(), localVarDict->getObject(canonicalKey));
16248dd02465SApple OSS Distributions 			}
1625c1dac77fSApple OSS Distributions 		}
1626855239e5SApple OSS Distributions 	}
1627e6231be0SApple OSS Distributions exit:
1628*8d741a5dSApple OSS Distributions 	return returnDict;
1629*8d741a5dSApple OSS Distributions }
1630bb611c8fSApple OSS Distributions 
1631*8d741a5dSApple OSS Distributions bool
serializeProperties(OSSerialize * s) const1632*8d741a5dSApple OSS Distributions IODTNVRAM::serializeProperties(OSSerialize *s) const
1633*8d741a5dSApple OSS Distributions {
1634*8d741a5dSApple OSS Distributions 	bool ok = false;
1635*8d741a5dSApple OSS Distributions 	OSSharedPtr<OSDictionary> dict;
1636*8d741a5dSApple OSS Distributions 
1637*8d741a5dSApple OSS Distributions 	dict = dictionaryWithProperties();
1638*8d741a5dSApple OSS Distributions 	if (dict) {
1639*8d741a5dSApple OSS Distributions 		ok = dict->serialize(s);
1640*8d741a5dSApple OSS Distributions 	}
1641*8d741a5dSApple OSS Distributions 
1642*8d741a5dSApple OSS Distributions 	DEBUG_INFO("ok=%d\n", ok);
1643e6231be0SApple OSS Distributions 	return ok;
1644e6231be0SApple OSS Distributions }
1645c1dac77fSApple OSS Distributions 
1646bb611c8fSApple OSS Distributions IOReturn
flushGUID(const uuid_t guid,IONVRAMOperation op)1647aca3beaaSApple OSS Distributions IODTNVRAM::flushGUID(const uuid_t guid, IONVRAMOperation op)
1648bb611c8fSApple OSS Distributions {
16495c2921b0SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
1650bb611c8fSApple OSS Distributions 
1651aca3beaaSApple OSS Distributions 	if (_format->getSystemPartitionActive() && (uuid_compare(guid, gAppleSystemVariableGuid) == 0)) {
16525c2921b0SApple OSS Distributions 		ret = _format->flush(guid, op);
1653bb611c8fSApple OSS Distributions 
1654aca3beaaSApple OSS Distributions 		DEBUG_INFO("system variables flushed, ret=%08x\n", ret);
1655aca3beaaSApple OSS Distributions 	} else if (uuid_compare(guid, gAppleNVRAMGuid) == 0) {
16565c2921b0SApple OSS Distributions 		ret = _format->flush(guid, op);
16575c2921b0SApple OSS Distributions 
1658aca3beaaSApple OSS Distributions 		DEBUG_INFO("common variables flushed, ret=%08x\n", ret);
1659bb611c8fSApple OSS Distributions 	}
1660bb611c8fSApple OSS Distributions 
16615c2921b0SApple OSS Distributions 	return ret;
1662e6231be0SApple OSS Distributions }
1663e6231be0SApple OSS Distributions 
1664e6231be0SApple OSS Distributions bool
handleSpecialVariables(const char * name,const uuid_t guid,const OSObject * obj,IOReturn * error)16655c2921b0SApple OSS Distributions IODTNVRAM::handleSpecialVariables(const char *name, const uuid_t guid, const OSObject *obj, IOReturn *error)
1666e6231be0SApple OSS Distributions {
16675c2921b0SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
1668e6231be0SApple OSS Distributions 	bool special = false;
1669e6231be0SApple OSS Distributions 
1670e6231be0SApple OSS Distributions 	NVRAMLOCKASSERTEXCLUSIVE();
1671e6231be0SApple OSS Distributions 
1672e6231be0SApple OSS Distributions 	// ResetNVRam flushes both regions in one call
1673e6231be0SApple OSS Distributions 	// Obliterate can flush either separately
1674e6231be0SApple OSS Distributions 	if (strcmp(name, "ObliterateNVRam") == 0) {
1675bb611c8fSApple OSS Distributions 		special = true;
1676aca3beaaSApple OSS Distributions 		ret = flushGUID(guid, kIONVRAMOperationObliterate);
1677e6231be0SApple OSS Distributions 	} else if (strcmp(name, "ResetNVRam") == 0) {
1678e6231be0SApple OSS Distributions 		special = true;
1679aca3beaaSApple OSS Distributions 		ret = flushGUID(gAppleSystemVariableGuid, kIONVRAMOperationReset);
1680e6231be0SApple OSS Distributions 
16815c2921b0SApple OSS Distributions 		if (ret != kIOReturnSuccess) {
1682e6231be0SApple OSS Distributions 			goto exit;
1683e6231be0SApple OSS Distributions 		}
1684e6231be0SApple OSS Distributions 
1685aca3beaaSApple OSS Distributions 		ret = flushGUID(gAppleNVRAMGuid, kIONVRAMOperationReset);
1686bb611c8fSApple OSS Distributions 	}
1687bb611c8fSApple OSS Distributions 
1688bb611c8fSApple OSS Distributions exit:
1689bb611c8fSApple OSS Distributions 	if (error) {
16905c2921b0SApple OSS Distributions 		*error = ret;
1691bb611c8fSApple OSS Distributions 	}
1692bb611c8fSApple OSS Distributions 
1693bb611c8fSApple OSS Distributions 	return special;
1694bb611c8fSApple OSS Distributions }
1695bb611c8fSApple OSS Distributions 
1696bb611c8fSApple OSS Distributions OSSharedPtr<OSObject>
copyPropertyWithGUIDAndName(const uuid_t guid,const char * name) const16975c2921b0SApple OSS Distributions IODTNVRAM::copyPropertyWithGUIDAndName(const uuid_t guid, const char *name) const
1698c1dac77fSApple OSS Distributions {
1699aca3beaaSApple OSS Distributions 	OSSharedPtr<const OSSymbol> canonicalKey;
1700aca3beaaSApple OSS Distributions 	OSSharedPtr<OSObject>       theObject;
1701aca3beaaSApple OSS Distributions 	uuid_t                      newGuid;
1702c1dac77fSApple OSS Distributions 
1703aca3beaaSApple OSS Distributions 	if (_varDict == nullptr) {
1704e6231be0SApple OSS Distributions 		DEBUG_INFO("No dictionary\n");
1705bb611c8fSApple OSS Distributions 		goto exit;
1706a5e72196SApple OSS Distributions 	}
1707c1dac77fSApple OSS Distributions 
1708aca3beaaSApple OSS Distributions 	if (!verifyPermission(kIONVRAMOperationRead, guid, name, _format->getSystemPartitionActive())) {
1709bb611c8fSApple OSS Distributions 		DEBUG_INFO("Not privileged\n");
1710bb611c8fSApple OSS Distributions 		goto exit;
1711a5e72196SApple OSS Distributions 	}
1712a3bb9fccSApple OSS Distributions 
1713aca3beaaSApple OSS Distributions 	translateGUID(guid, name, newGuid, _format->getSystemPartitionActive());
1714aca3beaaSApple OSS Distributions 
1715aca3beaaSApple OSS Distributions 	canonicalKey = keyWithGuidAndCString(newGuid, name);
1716aca3beaaSApple OSS Distributions 
1717e6231be0SApple OSS Distributions 	NVRAMREADLOCK();
1718aca3beaaSApple OSS Distributions 	theObject.reset(_varDict->getObject(canonicalKey.get()), OSRetain);
1719bb611c8fSApple OSS Distributions 	NVRAMUNLOCK();
1720bb611c8fSApple OSS Distributions 
1721e6231be0SApple OSS Distributions 	if (_diags) {
1722aca3beaaSApple OSS Distributions 		_diags->logVariable(getPartitionTypeForGUID(newGuid), kIONVRAMOperationRead, name, NULL);
1723e6231be0SApple OSS Distributions 	}
1724e6231be0SApple OSS Distributions 
1725bb611c8fSApple OSS Distributions 	if (theObject != nullptr) {
1726aca3beaaSApple OSS Distributions 		DEBUG_INFO("%s has object\n", canonicalKey.get()->getCStringNoCopy());
1727aca3beaaSApple OSS Distributions 	} else {
1728aca3beaaSApple OSS Distributions 		DEBUG_INFO("%s no entry\n", canonicalKey.get()->getCStringNoCopy());
1729bb611c8fSApple OSS Distributions 	}
1730bb611c8fSApple OSS Distributions 
1731bb611c8fSApple OSS Distributions exit:
1732a3bb9fccSApple OSS Distributions 	return theObject;
1733c1dac77fSApple OSS Distributions }
1734c1dac77fSApple OSS Distributions 
1735bb611c8fSApple OSS Distributions OSSharedPtr<OSObject>
copyProperty(const OSSymbol * aKey) const1736e6231be0SApple OSS Distributions IODTNVRAM::copyProperty(const OSSymbol *aKey) const
1737e6231be0SApple OSS Distributions {
1738e6231be0SApple OSS Distributions 	const char            *variableName;
1739e6231be0SApple OSS Distributions 	uuid_t                varGuid;
1740e6231be0SApple OSS Distributions 
1741e6231be0SApple OSS Distributions 	if (skipKey(aKey)) {
1742e6231be0SApple OSS Distributions 		return nullptr;
1743e6231be0SApple OSS Distributions 	}
1744e6231be0SApple OSS Distributions 	DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
1745e6231be0SApple OSS Distributions 
1746e6231be0SApple OSS Distributions 	parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
1747e6231be0SApple OSS Distributions 
17485c2921b0SApple OSS Distributions 	return copyPropertyWithGUIDAndName(varGuid, variableName);
1749e6231be0SApple OSS Distributions }
1750e6231be0SApple OSS Distributions 
1751e6231be0SApple OSS Distributions OSSharedPtr<OSObject>
copyProperty(const char * aKey) const1752a5e72196SApple OSS Distributions IODTNVRAM::copyProperty(const char *aKey) const
1753c1dac77fSApple OSS Distributions {
1754bb611c8fSApple OSS Distributions 	OSSharedPtr<const OSSymbol> keySymbol;
1755bb611c8fSApple OSS Distributions 	OSSharedPtr<OSObject>       theObject;
1756c1dac77fSApple OSS Distributions 
1757a3bb9fccSApple OSS Distributions 	keySymbol = OSSymbol::withCString(aKey);
1758bb611c8fSApple OSS Distributions 	if (keySymbol != nullptr) {
1759bb611c8fSApple OSS Distributions 		theObject = copyProperty(keySymbol.get());
1760c1dac77fSApple OSS Distributions 	}
1761c1dac77fSApple OSS Distributions 
1762c1dac77fSApple OSS Distributions 	return theObject;
1763c1dac77fSApple OSS Distributions }
1764c1dac77fSApple OSS Distributions 
1765a5e72196SApple OSS Distributions OSObject *
getProperty(const OSSymbol * aKey) const1766a5e72196SApple OSS Distributions IODTNVRAM::getProperty(const OSSymbol *aKey) const
1767a3bb9fccSApple OSS Distributions {
1768bb611c8fSApple OSS Distributions 	// The shared pointer gets released at the end of the function,
1769bb611c8fSApple OSS Distributions 	// and returns a view into theObject.
1770bb611c8fSApple OSS Distributions 	OSSharedPtr<OSObject> theObject = copyProperty(aKey);
1771a3bb9fccSApple OSS Distributions 
1772bb611c8fSApple OSS Distributions 	return theObject.get();
1773a3bb9fccSApple OSS Distributions }
1774a3bb9fccSApple OSS Distributions 
1775a5e72196SApple OSS Distributions OSObject *
getProperty(const char * aKey) const1776a5e72196SApple OSS Distributions IODTNVRAM::getProperty(const char *aKey) const
1777a3bb9fccSApple OSS Distributions {
1778bb611c8fSApple OSS Distributions 	// The shared pointer gets released at the end of the function,
1779bb611c8fSApple OSS Distributions 	// and returns a view into theObject.
1780bb611c8fSApple OSS Distributions 	OSSharedPtr<OSObject> theObject = copyProperty(aKey);
1781a3bb9fccSApple OSS Distributions 
1782bb611c8fSApple OSS Distributions 	return theObject.get();
1783a3bb9fccSApple OSS Distributions }
1784a3bb9fccSApple OSS Distributions 
1785a5e72196SApple OSS Distributions IOReturn
setPropertyWithGUIDAndName(const uuid_t guid,const char * name,OSObject * anObject)17865c2921b0SApple OSS Distributions IODTNVRAM::setPropertyWithGUIDAndName(const uuid_t guid, const char *name, OSObject *anObject)
1787c1dac77fSApple OSS Distributions {
1788e6231be0SApple OSS Distributions 	IOReturn              ret = kIOReturnSuccess;
1789bb611c8fSApple OSS Distributions 	bool                  remove = false;
1790bb611c8fSApple OSS Distributions 	OSString              *tmpString = nullptr;
1791e7776783SApple OSS Distributions 	OSSharedPtr<OSObject> propObject;
1792bb611c8fSApple OSS Distributions 	OSSharedPtr<OSObject> sharedObject(anObject, OSRetain);
179394d3b452SApple OSS Distributions 	bool                  deletePropertyKey, syncNowPropertyKey, forceSyncNowPropertyKey, deletePropertyKeyWRet;
1794e6231be0SApple OSS Distributions 	bool                  ok;
1795bb611c8fSApple OSS Distributions 	size_t                propDataSize = 0;
1796aca3beaaSApple OSS Distributions 	uuid_t                newGuid;
1797c1dac77fSApple OSS Distributions 
1798e6231be0SApple OSS Distributions 	deletePropertyKey = strncmp(name, kIONVRAMDeletePropertyKey, sizeof(kIONVRAMDeletePropertyKey)) == 0;
179994d3b452SApple OSS Distributions 	deletePropertyKeyWRet = strncmp(name, kIONVRAMDeletePropertyKeyWRet, sizeof(kIONVRAMDeletePropertyKeyWRet)) == 0;
1800e6231be0SApple OSS Distributions 	syncNowPropertyKey = strncmp(name, kIONVRAMSyncNowPropertyKey, sizeof(kIONVRAMSyncNowPropertyKey)) == 0;
1801e6231be0SApple OSS Distributions 	forceSyncNowPropertyKey = strncmp(name, kIONVRAMForceSyncNowPropertyKey, sizeof(kIONVRAMForceSyncNowPropertyKey)) == 0;
1802bb611c8fSApple OSS Distributions 
180394d3b452SApple OSS Distributions 	if (deletePropertyKey || deletePropertyKeyWRet) {
1804bb611c8fSApple OSS Distributions 		tmpString = OSDynamicCast(OSString, anObject);
1805bb611c8fSApple OSS Distributions 		if (tmpString != nullptr) {
1806e6231be0SApple OSS Distributions 			const char *variableName;
18075c2921b0SApple OSS Distributions 			uuid_t     valueVarGuid;
18085c2921b0SApple OSS Distributions 			bool       guidProvided;
1809e6231be0SApple OSS Distributions 			IOReturn   removeRet;
1810e6231be0SApple OSS Distributions 
18115c2921b0SApple OSS Distributions 			guidProvided = parseVariableName(tmpString->getCStringNoCopy(), &valueVarGuid, &variableName);
18125c2921b0SApple OSS Distributions 
18135c2921b0SApple OSS Distributions 			// nvram tool will provide a "nvram -d var" or "nvram -d guid:var" as
18145c2921b0SApple OSS Distributions 			// kIONVRAMDeletePropertyKey=var or kIONVRAMDeletePropertyKey=guid:var
18155c2921b0SApple OSS Distributions 			// that will come into this function as (gAppleNVRAMGuid, varname, nullptr)
18165c2921b0SApple OSS Distributions 			// if we provide the "-z" flag to the nvram tool this function will come in as
18175c2921b0SApple OSS Distributions 			// (gAppleSystemVariableGuid, varname, nullptr). We are reparsing the value string,
18185c2921b0SApple OSS Distributions 			// if there is a GUID provided with the value then use that GUID otherwise use the
18195c2921b0SApple OSS Distributions 			// guid that was provided via the node selection or default.
18205c2921b0SApple OSS Distributions 			if (guidProvided == false) {
18215c2921b0SApple OSS Distributions 				DEBUG_INFO("Removing with API provided GUID\n");
18225c2921b0SApple OSS Distributions 				removeRet = removePropertyWithGUIDAndName(guid, variableName);
18235c2921b0SApple OSS Distributions 			} else {
18245c2921b0SApple OSS Distributions 				DEBUG_INFO("Removing with value provided GUID\n");
18255c2921b0SApple OSS Distributions 				removeRet = removePropertyWithGUIDAndName(valueVarGuid, variableName);
18265c2921b0SApple OSS Distributions 			}
182794d3b452SApple OSS Distributions 			if (deletePropertyKeyWRet) {
182894d3b452SApple OSS Distributions 				ret = removeRet;
182994d3b452SApple OSS Distributions 			}
183094d3b452SApple OSS Distributions 			DEBUG_INFO("%s found, removeRet=%#08x\n", deletePropertyKeyWRet ? "deletePropertyKeyWRet" : "deletePropertyKey", removeRet);
1831bb611c8fSApple OSS Distributions 		} else {
183294d3b452SApple OSS Distributions 			DEBUG_INFO("%s value needs to be an OSString\n", deletePropertyKeyWRet ? "deletePropertyKeyWRet" : "deletePropertyKey");
1833e6231be0SApple OSS Distributions 			ret = kIOReturnError;
1834bb611c8fSApple OSS Distributions 		}
1835bb611c8fSApple OSS Distributions 		goto exit;
1836bb611c8fSApple OSS Distributions 	} else if (syncNowPropertyKey || forceSyncNowPropertyKey) {
1837bb611c8fSApple OSS Distributions 		tmpString = OSDynamicCast(OSString, anObject);
1838e6231be0SApple OSS Distributions 		DEBUG_INFO("NVRAM sync key %s found\n", name);
1839bb611c8fSApple OSS Distributions 		if (tmpString != nullptr) {
1840bb611c8fSApple OSS Distributions 			// We still want to throttle NVRAM commit rate for SyncNow. ForceSyncNow is provided as a really big hammer.
184194d3b452SApple OSS Distributions 			ret = syncInternal(syncNowPropertyKey);
1842bb611c8fSApple OSS Distributions 		} else {
1843e6231be0SApple OSS Distributions 			DEBUG_INFO("%s value needs to be an OSString\n", name);
1844e6231be0SApple OSS Distributions 			ret = kIOReturnError;
1845bb611c8fSApple OSS Distributions 		}
1846bb611c8fSApple OSS Distributions 		goto exit;
1847a5e72196SApple OSS Distributions 	}
1848c1dac77fSApple OSS Distributions 
1849aca3beaaSApple OSS Distributions 	if (!verifyPermission(kIONVRAMOperationWrite, guid, name, _format->getSystemPartitionActive())) {
1850bb611c8fSApple OSS Distributions 		DEBUG_INFO("Not privileged\n");
1851e6231be0SApple OSS Distributions 		ret = kIOReturnNotPrivileged;
1852bb611c8fSApple OSS Distributions 		goto exit;
1853a5e72196SApple OSS Distributions 	}
1854fad439e7SApple OSS Distributions 
1855c1dac77fSApple OSS Distributions 	// Make sure the object is of the correct type.
1856e6231be0SApple OSS Distributions 	switch (getVariableType(name)) {
1857c1dac77fSApple OSS Distributions 	case kOFVariableTypeBoolean:
1858bb611c8fSApple OSS Distributions 		propObject = OSDynamicPtrCast<OSBoolean>(sharedObject);
18595c2921b0SApple OSS Distributions 		if (propObject) {
18601031c584SApple OSS Distributions 			record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as bool to %d", name, ((OSBoolean *)propObject.get())->getValue());
18615c2921b0SApple OSS Distributions 		}
1862c1dac77fSApple OSS Distributions 		break;
1863c1dac77fSApple OSS Distributions 
1864c1dac77fSApple OSS Distributions 	case kOFVariableTypeNumber:
1865bb611c8fSApple OSS Distributions 		propObject = OSDynamicPtrCast<OSNumber>(sharedObject);
18665c2921b0SApple OSS Distributions 		if (propObject) {
18671031c584SApple OSS Distributions 			record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as number to %#llx", name, ((OSNumber *)propObject.get())->unsigned64BitValue());
18685c2921b0SApple OSS Distributions 		}
1869c1dac77fSApple OSS Distributions 		break;
1870c1dac77fSApple OSS Distributions 
1871c1dac77fSApple OSS Distributions 	case kOFVariableTypeString:
1872bb611c8fSApple OSS Distributions 		propObject = OSDynamicPtrCast<OSString>(sharedObject);
1873bb611c8fSApple OSS Distributions 		if (propObject != nullptr) {
18741031c584SApple OSS Distributions 			record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as string to %s", name, ((OSString *)propObject.get())->getCStringNoCopy());
18755c2921b0SApple OSS Distributions 
1876bb611c8fSApple OSS Distributions 			propDataSize = (OSDynamicPtrCast<OSString>(propObject))->getLength();
1877bb611c8fSApple OSS Distributions 
1878e6231be0SApple OSS Distributions 			if ((strncmp(name, kIONVRAMBootArgsKey, sizeof(kIONVRAMBootArgsKey)) == 0) && (propDataSize >= BOOT_LINE_LENGTH)) {
1879bb611c8fSApple OSS Distributions 				DEBUG_ERROR("boot-args size too large for BOOT_LINE_LENGTH, propDataSize=%zu\n", propDataSize);
1880e6231be0SApple OSS Distributions 				ret = kIOReturnNoSpace;
1881bb611c8fSApple OSS Distributions 				goto exit;
1882bb611c8fSApple OSS Distributions 			}
1883a5e72196SApple OSS Distributions 		}
1884c1dac77fSApple OSS Distributions 		break;
1885c1dac77fSApple OSS Distributions 
1886c1dac77fSApple OSS Distributions 	case kOFVariableTypeData:
1887bb611c8fSApple OSS Distributions 		propObject = OSDynamicPtrCast<OSData>(sharedObject);
1888bb611c8fSApple OSS Distributions 		if (propObject == nullptr) {
1889bb611c8fSApple OSS Distributions 			tmpString = OSDynamicCast(OSString, sharedObject.get());
1890bb611c8fSApple OSS Distributions 			if (tmpString != nullptr) {
1891c1dac77fSApple OSS Distributions 				propObject = OSData::withBytes(tmpString->getCStringNoCopy(),
1892c1dac77fSApple OSS Distributions 				    tmpString->getLength());
1893c1dac77fSApple OSS Distributions 			}
1894c1dac77fSApple OSS Distributions 		}
1895bb611c8fSApple OSS Distributions 
1896bb611c8fSApple OSS Distributions 		if (propObject != nullptr) {
1897bb611c8fSApple OSS Distributions 			propDataSize = (OSDynamicPtrCast<OSData>(propObject))->getLength();
18981031c584SApple OSS Distributions 			record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "write", "%s as data with size %#x", name, ((OSData *)propObject.get())->getLength());
1899bb611c8fSApple OSS Distributions 		}
1900bb611c8fSApple OSS Distributions 
1901bb611c8fSApple OSS Distributions #if defined(XNU_TARGET_OS_OSX)
1902bb611c8fSApple OSS Distributions 		if ((propObject != nullptr) && ((OSDynamicPtrCast<OSData>(propObject))->getLength() == 0)) {
1903bb611c8fSApple OSS Distributions 			remove = true;
1904bb611c8fSApple OSS Distributions 		}
1905bb611c8fSApple OSS Distributions #endif /* defined(XNU_TARGET_OS_OSX) */
1906bb611c8fSApple OSS Distributions 		break;
1907bb611c8fSApple OSS Distributions 	default:
1908c1dac77fSApple OSS Distributions 		break;
1909c1dac77fSApple OSS Distributions 	}
1910c1dac77fSApple OSS Distributions 
1911bb611c8fSApple OSS Distributions 	if (propObject == nullptr) {
19121031c584SApple OSS Distributions 		DEBUG_ERROR("No property object\n");
1913e6231be0SApple OSS Distributions 		ret = kIOReturnBadArgument;
1914bb611c8fSApple OSS Distributions 		goto exit;
1915bb611c8fSApple OSS Distributions 	}
1916bb611c8fSApple OSS Distributions 
1917e6231be0SApple OSS Distributions 	if (!verifyWriteSizeLimit(guid, name, propDataSize)) {
1918e6231be0SApple OSS Distributions 		DEBUG_ERROR("Property data size of %zu too long for %s\n", propDataSize, name);
1919e6231be0SApple OSS Distributions 		ret = kIOReturnNoSpace;
1920bb611c8fSApple OSS Distributions 		goto exit;
1921bb611c8fSApple OSS Distributions 	}
1922bb611c8fSApple OSS Distributions 
1923e6231be0SApple OSS Distributions 	NVRAMWRITELOCK();
1924e6231be0SApple OSS Distributions 	ok = handleSpecialVariables(name, guid, propObject.get(), &ret);
1925e6231be0SApple OSS Distributions 	NVRAMUNLOCK();
1926bb611c8fSApple OSS Distributions 
1927e6231be0SApple OSS Distributions 	if (ok) {
1928e6231be0SApple OSS Distributions 		goto exit;
1929bb611c8fSApple OSS Distributions 	}
1930bb611c8fSApple OSS Distributions 
1931bb611c8fSApple OSS Distributions 	if (remove == false) {
1932bb611c8fSApple OSS Distributions 		DEBUG_INFO("Adding object\n");
1933aca3beaaSApple OSS Distributions 
1934aca3beaaSApple OSS Distributions 		translateGUID(guid, name, newGuid, _format->getSystemPartitionActive());
1935aca3beaaSApple OSS Distributions 
1936e6231be0SApple OSS Distributions 		NVRAMWRITELOCK();
1937aca3beaaSApple OSS Distributions 
1938aca3beaaSApple OSS Distributions 		ret = _format->setVariable(newGuid, name, propObject.get());
1939aca3beaaSApple OSS Distributions 
1940e6231be0SApple OSS Distributions 		NVRAMUNLOCK();
1941bb611c8fSApple OSS Distributions 	} else {
1942bb611c8fSApple OSS Distributions 		DEBUG_INFO("Removing object\n");
1943e6231be0SApple OSS Distributions 		ret = removePropertyWithGUIDAndName(guid, name);
1944a5e72196SApple OSS Distributions 	}
1945c1dac77fSApple OSS Distributions 
1946cc9a6355SApple OSS Distributions 	if (tmpString) {
1947bb611c8fSApple OSS Distributions 		propObject.reset();
1948cc9a6355SApple OSS Distributions 	}
1949cc9a6355SApple OSS Distributions 
1950bb611c8fSApple OSS Distributions exit:
1951e6231be0SApple OSS Distributions 	DEBUG_INFO("ret=%#08x\n", ret);
1952c1dac77fSApple OSS Distributions 
1953e6231be0SApple OSS Distributions 	return ret;
1954e6231be0SApple OSS Distributions }
1955e6231be0SApple OSS Distributions 
1956e6231be0SApple OSS Distributions IOReturn
setPropertyInternal(const OSSymbol * aKey,OSObject * anObject)1957e6231be0SApple OSS Distributions IODTNVRAM::setPropertyInternal(const OSSymbol *aKey, OSObject *anObject)
1958e6231be0SApple OSS Distributions {
1959e6231be0SApple OSS Distributions 	const char *variableName;
1960e6231be0SApple OSS Distributions 	uuid_t     varGuid;
1961e6231be0SApple OSS Distributions 
1962e6231be0SApple OSS Distributions 	DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
1963e6231be0SApple OSS Distributions 
1964e6231be0SApple OSS Distributions 	parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
1965e6231be0SApple OSS Distributions 
19665c2921b0SApple OSS Distributions 	return setPropertyWithGUIDAndName(varGuid, variableName, anObject);
1967c1dac77fSApple OSS Distributions }
1968c1dac77fSApple OSS Distributions 
1969a5e72196SApple OSS Distributions bool
setProperty(const OSSymbol * aKey,OSObject * anObject)1970a5e72196SApple OSS Distributions IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject)
1971a5e72196SApple OSS Distributions {
1972a5e72196SApple OSS Distributions 	return setPropertyInternal(aKey, anObject) == kIOReturnSuccess;
1973a5e72196SApple OSS Distributions }
1974a5e72196SApple OSS Distributions 
1975a5e72196SApple OSS Distributions void
removeProperty(const OSSymbol * aKey)1976a5e72196SApple OSS Distributions IODTNVRAM::removeProperty(const OSSymbol *aKey)
197714e3d835SApple OSS Distributions {
1978bb611c8fSApple OSS Distributions 	IOReturn ret;
197914e3d835SApple OSS Distributions 
1980bb611c8fSApple OSS Distributions 	ret = removePropertyInternal(aKey);
1981bb611c8fSApple OSS Distributions 
1982e7776783SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
1983e6231be0SApple OSS Distributions 		DEBUG_INFO("removePropertyInternal failed, ret=%#08x\n", ret);
1984e6231be0SApple OSS Distributions 	}
1985e6231be0SApple OSS Distributions }
1986e6231be0SApple OSS Distributions 
1987e6231be0SApple OSS Distributions IOReturn
removePropertyWithGUIDAndName(const uuid_t guid,const char * name)19885c2921b0SApple OSS Distributions IODTNVRAM::removePropertyWithGUIDAndName(const uuid_t guid, const char *name)
1989e6231be0SApple OSS Distributions {
1990aca3beaaSApple OSS Distributions 	IOReturn ret;
1991aca3beaaSApple OSS Distributions 	uuid_t   newGuid;
1992e6231be0SApple OSS Distributions 
1993aca3beaaSApple OSS Distributions 	DEBUG_INFO("name=%s\n", name);
1994e6231be0SApple OSS Distributions 
1995aca3beaaSApple OSS Distributions 	if (_varDict == nullptr) {
1996aca3beaaSApple OSS Distributions 		DEBUG_INFO("No dictionary\n");
1997aca3beaaSApple OSS Distributions 		ret = kIOReturnNotFound;
1998aca3beaaSApple OSS Distributions 		goto exit;
1999aca3beaaSApple OSS Distributions 	}
2000e6231be0SApple OSS Distributions 
2001aca3beaaSApple OSS Distributions 	if (!verifyPermission(kIONVRAMOperationDelete, guid, name, _format->getSystemPartitionActive())) {
2002aca3beaaSApple OSS Distributions 		DEBUG_INFO("Not privileged\n");
2003e6231be0SApple OSS Distributions 		ret = kIOReturnNotPrivileged;
2004e6231be0SApple OSS Distributions 		goto exit;
2005e6231be0SApple OSS Distributions 	}
2006e6231be0SApple OSS Distributions 
2007aca3beaaSApple OSS Distributions 	translateGUID(guid, name, newGuid, _format->getSystemPartitionActive());
2008aca3beaaSApple OSS Distributions 
2009e6231be0SApple OSS Distributions 	NVRAMWRITELOCK();
2010e6231be0SApple OSS Distributions 
2011aca3beaaSApple OSS Distributions 	ret = _format->setVariable(newGuid, name, nullptr);
2012aca3beaaSApple OSS Distributions 
2013aca3beaaSApple OSS Distributions 	if (ret != kIOReturnSuccess) {
2014e6231be0SApple OSS Distributions 		DEBUG_INFO("%s not found\n", name);
2015e7776783SApple OSS Distributions 		ret = kIOReturnNotFound;
2016e6231be0SApple OSS Distributions 	}
2017e6231be0SApple OSS Distributions 
2018bb611c8fSApple OSS Distributions 	NVRAMUNLOCK();
2019bb611c8fSApple OSS Distributions 
20205c2921b0SApple OSS Distributions 	record_system_event(SYSTEM_EVENT_TYPE_INFO, SYSTEM_EVENT_SUBSYSTEM_NVRAM, "delete", "%s", name);
20215c2921b0SApple OSS Distributions 
2022e6231be0SApple OSS Distributions exit:
2023e6231be0SApple OSS Distributions 	return ret;
2024a5e72196SApple OSS Distributions }
202514e3d835SApple OSS Distributions 
2026bb611c8fSApple OSS Distributions IOReturn
removePropertyInternal(const OSSymbol * aKey)2027bb611c8fSApple OSS Distributions IODTNVRAM::removePropertyInternal(const OSSymbol *aKey)
2028bb611c8fSApple OSS Distributions {
2029e6231be0SApple OSS Distributions 	IOReturn   ret;
2030bb611c8fSApple OSS Distributions 	const char *variableName;
2031bb611c8fSApple OSS Distributions 	uuid_t     varGuid;
2032bb611c8fSApple OSS Distributions 
2033bb611c8fSApple OSS Distributions 	DEBUG_INFO("aKey=%s\n", aKey->getCStringNoCopy());
2034bb611c8fSApple OSS Distributions 
2035bb611c8fSApple OSS Distributions 	parseVariableName(aKey->getCStringNoCopy(), &varGuid, &variableName);
2036bb611c8fSApple OSS Distributions 
20375c2921b0SApple OSS Distributions 	ret = removePropertyWithGUIDAndName(varGuid, variableName);
203814e3d835SApple OSS Distributions 
2039e6231be0SApple OSS Distributions 	return ret;
204014e3d835SApple OSS Distributions }
204114e3d835SApple OSS Distributions 
2042a5e72196SApple OSS Distributions IOReturn
setProperties(OSObject * properties)2043a5e72196SApple OSS Distributions IODTNVRAM::setProperties(OSObject *properties)
2044c1dac77fSApple OSS Distributions {
2045e6231be0SApple OSS Distributions 	IOReturn                          ret = kIOReturnSuccess;
2046c1dac77fSApple OSS Distributions 	OSObject                          *object;
2047c1dac77fSApple OSS Distributions 	const OSSymbol                    *key;
2048c1dac77fSApple OSS Distributions 	OSDictionary                      *dict;
2049bb611c8fSApple OSS Distributions 	OSSharedPtr<OSCollectionIterator> iter;
2050c1dac77fSApple OSS Distributions 
2051c1dac77fSApple OSS Distributions 	dict = OSDynamicCast(OSDictionary, properties);
2052bb611c8fSApple OSS Distributions 	if (dict == nullptr) {
2053bb611c8fSApple OSS Distributions 		DEBUG_ERROR("Not a dictionary\n");
2054a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2055a5e72196SApple OSS Distributions 	}
2056c1dac77fSApple OSS Distributions 
2057c1dac77fSApple OSS Distributions 	iter = OSCollectionIterator::withCollection(dict);
2058bb611c8fSApple OSS Distributions 	if (iter == nullptr) {
2059bb611c8fSApple OSS Distributions 		DEBUG_ERROR("Couldn't create iterator\n");
2060a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
2061a5e72196SApple OSS Distributions 	}
2062c1dac77fSApple OSS Distributions 
2063e6231be0SApple OSS Distributions 	while (ret == kIOReturnSuccess) {
2064c1dac77fSApple OSS Distributions 		key = OSDynamicCast(OSSymbol, iter->getNextObject());
2065bb611c8fSApple OSS Distributions 		if (key == nullptr) {
2066a5e72196SApple OSS Distributions 			break;
2067a5e72196SApple OSS Distributions 		}
2068c1dac77fSApple OSS Distributions 
2069c1dac77fSApple OSS Distributions 		object = dict->getObject(key);
2070bb611c8fSApple OSS Distributions 		if (object == nullptr) {
2071a5e72196SApple OSS Distributions 			continue;
2072a5e72196SApple OSS Distributions 		}
2073c1dac77fSApple OSS Distributions 
2074e6231be0SApple OSS Distributions 		ret = setPropertyInternal(key, object);
207514e3d835SApple OSS Distributions 	}
2076c1dac77fSApple OSS Distributions 
2077e6231be0SApple OSS Distributions 	DEBUG_INFO("ret=%#08x\n", ret);
2078c1dac77fSApple OSS Distributions 
2079e6231be0SApple OSS Distributions 	return ret;
2080c1dac77fSApple OSS Distributions }
2081c1dac77fSApple OSS Distributions 
2082e7776783SApple OSS Distributions // ********************** Deprecated ********************
2083e7776783SApple OSS Distributions 
2084a5e72196SApple OSS Distributions IOReturn
readXPRAM(IOByteCount offset,uint8_t * buffer,IOByteCount length)2085e7776783SApple OSS Distributions IODTNVRAM::readXPRAM(IOByteCount offset, uint8_t *buffer,
2086c1dac77fSApple OSS Distributions     IOByteCount length)
2087c1dac77fSApple OSS Distributions {
2088a3bb9fccSApple OSS Distributions 	return kIOReturnUnsupported;
2089c1dac77fSApple OSS Distributions }
2090c1dac77fSApple OSS Distributions 
2091a5e72196SApple OSS Distributions IOReturn
writeXPRAM(IOByteCount offset,uint8_t * buffer,IOByteCount length)2092e7776783SApple OSS Distributions IODTNVRAM::writeXPRAM(IOByteCount offset, uint8_t *buffer,
2093c1dac77fSApple OSS Distributions     IOByteCount length)
2094c1dac77fSApple OSS Distributions {
2095a3bb9fccSApple OSS Distributions 	return kIOReturnUnsupported;
2096c1dac77fSApple OSS Distributions }
2097c1dac77fSApple OSS Distributions 
2098a5e72196SApple OSS Distributions IOReturn
readNVRAMProperty(IORegistryEntry * entry,const OSSymbol ** name,OSData ** value)2099a5e72196SApple OSS Distributions IODTNVRAM::readNVRAMProperty(IORegistryEntry *entry,
2100c1dac77fSApple OSS Distributions     const OSSymbol **name,
2101c1dac77fSApple OSS Distributions     OSData **value)
2102c1dac77fSApple OSS Distributions {
2103e7776783SApple OSS Distributions 	return kIOReturnUnsupported;
2104c1dac77fSApple OSS Distributions }
2105c1dac77fSApple OSS Distributions 
2106a5e72196SApple OSS Distributions IOReturn
writeNVRAMProperty(IORegistryEntry * entry,const OSSymbol * name,OSData * value)2107a5e72196SApple OSS Distributions IODTNVRAM::writeNVRAMProperty(IORegistryEntry *entry,
2108c1dac77fSApple OSS Distributions     const OSSymbol *name,
2109c1dac77fSApple OSS Distributions     OSData *value)
2110c1dac77fSApple OSS Distributions {
2111e7776783SApple OSS Distributions 	return kIOReturnUnsupported;
2112c1dac77fSApple OSS Distributions }
2113c1dac77fSApple OSS Distributions 
2114a5e72196SApple OSS Distributions OSDictionary *
getNVRAMPartitions(void)2115a5e72196SApple OSS Distributions IODTNVRAM::getNVRAMPartitions(void)
2116fad439e7SApple OSS Distributions {
2117e7776783SApple OSS Distributions 	return NULL;
2118fad439e7SApple OSS Distributions }
2119c1dac77fSApple OSS Distributions 
2120a5e72196SApple OSS Distributions IOReturn
readNVRAMPartition(const OSSymbol * partitionID,IOByteCount offset,uint8_t * buffer,IOByteCount length)2121a5e72196SApple OSS Distributions IODTNVRAM::readNVRAMPartition(const OSSymbol *partitionID,
2122e7776783SApple OSS Distributions     IOByteCount offset, uint8_t *buffer,
2123fad439e7SApple OSS Distributions     IOByteCount length)
2124fad439e7SApple OSS Distributions {
2125e7776783SApple OSS Distributions 	return kIOReturnUnsupported;
2126fad439e7SApple OSS Distributions }
2127fad439e7SApple OSS Distributions 
2128a5e72196SApple OSS Distributions IOReturn
writeNVRAMPartition(const OSSymbol * partitionID,IOByteCount offset,uint8_t * buffer,IOByteCount length)2129a5e72196SApple OSS Distributions IODTNVRAM::writeNVRAMPartition(const OSSymbol *partitionID,
2130e7776783SApple OSS Distributions     IOByteCount offset, uint8_t *buffer,
2131fad439e7SApple OSS Distributions     IOByteCount length)
2132fad439e7SApple OSS Distributions {
2133e7776783SApple OSS Distributions 	return kIOReturnUnsupported;
2134fad439e7SApple OSS Distributions }
2135fad439e7SApple OSS Distributions 
2136a5e72196SApple OSS Distributions IOByteCount
savePanicInfo(uint8_t * buffer,IOByteCount length)2137e7776783SApple OSS Distributions IODTNVRAM::savePanicInfo(uint8_t *buffer, IOByteCount length)
2138fad439e7SApple OSS Distributions {
2139a5e72196SApple OSS Distributions 	return 0;
2140a5e72196SApple OSS Distributions }
2141