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